toolroll 0.9.84 → 0.9.86
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/CHANGELOG.md +66 -0
- package/README.md +94 -1193
- package/dist/agent-fence.d.ts +9 -5
- package/dist/agent-fence.js +6 -5
- package/dist/agent-onboard.d.ts +2 -0
- package/dist/agent-onboard.js +3 -0
- package/dist/assignment.js +4 -3
- package/dist/browser/workspace.css +1 -1
- package/dist/browser/workspace.js +33 -31
- package/dist/browser-workspace.d.ts +45 -0
- package/dist/chat-actions.d.ts +11 -1
- package/dist/chat-actions.js +53 -1
- package/dist/chat-channel.d.ts +10 -1
- package/dist/chat-channel.js +36 -5
- package/dist/chat-decide.d.ts +16 -4
- package/dist/chat-decide.js +239 -31
- package/dist/chat-messages.d.ts +5 -0
- package/dist/chat-messages.js +1 -1
- package/dist/chat-quiet.js +6 -4
- package/dist/chat-review.d.ts +4 -0
- package/dist/chat-review.js +13 -4
- package/dist/chat-terms.d.ts +9 -0
- package/dist/chat-terms.js +46 -0
- package/dist/claim.d.ts +3 -0
- package/dist/claim.js +4 -1
- package/dist/contracts/chat-actions.d.ts +9 -0
- package/dist/contracts/chat-actions.js +3 -0
- package/dist/contracts/console-api.d.ts +6 -2
- package/dist/contracts/console-api.js +6 -2
- package/dist/contracts/flow-propose.d.ts +4 -1
- package/dist/contracts/flow-propose.js +1 -1
- package/dist/contracts/flow.d.ts +41 -0
- package/dist/contracts/flow.js +4 -2
- package/dist/contracts/lead-tools.d.ts +51 -0
- package/dist/contracts/lead-tools.js +5 -0
- package/dist/contracts/store-json.d.ts +2 -0
- package/dist/contracts/trigger-payloads.d.ts +20 -0
- package/dist/contracts/trigger-payloads.js +4 -0
- package/dist/contracts/youiyoux-request.d.ts +248 -0
- package/dist/contracts/youiyoux-request.js +152 -0
- package/dist/coordinator.js +1 -0
- package/dist/deploy-gate.js +4 -0
- package/dist/dispatch.d.ts +3 -0
- package/dist/dispatch.js +4 -1
- package/dist/flow-browser.d.ts +103 -0
- package/dist/flow-browser.js +204 -0
- package/dist/flow-cadence.d.ts +8 -2
- package/dist/flow-cadence.js +16 -3
- package/dist/flow-card-task.d.ts +9 -0
- package/dist/flow-card-task.js +15 -6
- package/dist/flow-code.d.ts +5 -1
- package/dist/flow-code.js +4 -1
- package/dist/flow-engine.js +16 -0
- package/dist/flow-live.js +9 -1
- package/dist/flow-pull-request.js +15 -7
- package/dist/flow-share.js +3 -1
- package/dist/flow-steps.d.ts +9 -1
- package/dist/flow-steps.js +55 -5
- package/dist/flow-triggers.js +55 -0
- package/dist/flows-cli.d.ts +19 -0
- package/dist/flows-cli.js +47 -2
- package/dist/flows-ui.js +11 -2
- package/dist/flows.js +5 -2
- package/dist/integrations-ui.js +9 -4
- package/dist/integrations.d.ts +9 -1
- package/dist/integrations.js +43 -2
- package/dist/landed-cleanup.d.ts +4 -0
- package/dist/landed-cleanup.js +3 -2
- package/dist/lead-capabilities.js +2 -1
- package/dist/lead-cli.js +3 -1
- package/dist/lead-tools.d.ts +2 -0
- package/dist/lead-tools.js +65 -10
- package/dist/lead-voice.js +16 -5
- package/dist/lead.d.ts +2 -0
- package/dist/lead.js +3 -3
- package/dist/operate.d.ts +2 -3
- package/dist/operate.js +226 -21
- package/dist/project-activity.d.ts +20 -0
- package/dist/project-activity.js +23 -0
- package/dist/project-cli.d.ts +1 -0
- package/dist/project-cli.js +36 -19
- package/dist/project-delete.js +7 -3
- package/dist/project-knowledge.d.ts +3 -3
- package/dist/project-outcomes.d.ts +119 -0
- package/dist/project-outcomes.js +79 -0
- package/dist/pull-request-flow.js +35 -4
- package/dist/result-actions.d.ts +4 -0
- package/dist/result-actions.js +41 -9
- package/dist/result-follow-ups.js +4 -0
- package/dist/result-review.d.ts +9 -0
- package/dist/result-review.js +45 -5
- package/dist/scope.d.ts +5 -0
- package/dist/scope.js +7 -0
- package/dist/server/chat.js +4 -2
- package/dist/server/console.css +41 -0
- package/dist/server/flows.js +15 -0
- package/dist/server/pages.js +11 -1
- package/dist/server/render-chat.js +3 -2
- package/dist/server/render-pages.d.ts +15 -2
- package/dist/server/render-pages.js +52 -4
- package/dist/server/render-results.d.ts +2 -0
- package/dist/server/render-results.js +20 -7
- package/dist/server/render-tasks.d.ts +9 -0
- package/dist/server/render-tasks.js +32 -11
- package/dist/server/route-table.js +12 -0
- package/dist/server/settings.js +18 -1
- package/dist/server/task-views.js +11 -0
- package/dist/server/tasks.d.ts +10 -0
- package/dist/server/tasks.js +95 -7
- package/dist/settings-proofs.js +1 -0
- package/dist/store.d.ts +116 -5
- package/dist/store.js +385 -24
- package/dist/surface.js +18 -2
- package/dist/task-archive.d.ts +10 -0
- package/dist/task-archive.js +16 -0
- package/dist/task-control.d.ts +1 -1
- package/dist/task-source.d.ts +13 -1
- package/dist/task-source.js +17 -1
- package/dist/telegram-lead.js +7 -5
- package/dist/telegram.js +1 -1
- package/dist/tidy.d.ts +130 -0
- package/dist/tidy.js +503 -0
- package/dist/toolroll-update.js +2 -2
- package/dist/webhooks.d.ts +6 -0
- package/dist/webhooks.js +25 -0
- package/dist/work-index.d.ts +28 -0
- package/dist/work-index.js +82 -28
- package/dist/workspace-ui.d.ts +1 -1
- package/dist/workspace-ui.js +3 -2
- package/dist/youiyoux-intake.d.ts +234 -0
- package/dist/youiyoux-intake.js +908 -0
- package/package.json +11 -8
package/dist/lead-tools.js
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
|
+
import { sameFeedbackImage } from "./result-review.js";
|
|
1
2
|
import { sweepLine, sweepTable } from "./lead-sweep.js";
|
|
2
3
|
import { connectionsOf, oneClickOf } from "./mcp-connect.js";
|
|
3
4
|
import { checkLevelFromWords, isCheckLevel } from "./check-levels.js";
|
|
4
5
|
import { policyParts } from "./policy.js";
|
|
5
6
|
import { randomUUID } from 'node:crypto';
|
|
6
7
|
import { dirname, join } from 'node:path';
|
|
8
|
+
import { projectOutcomes, projectOutcomesPage } from './project-outcomes.js';
|
|
7
9
|
import { repositoryContextRead } from './repository-context.js';
|
|
8
10
|
import { assignmentCatchUp } from './assignment-brief.js';
|
|
11
|
+
import { browserViewOf } from './flow-browser.js';
|
|
9
12
|
import { CHAT_ACTIONS, CHAT_ACTION_FIELDS, isChatAction, prepareSharedAction, sharedActionNeedsReview, sharedActionPayload } from './chat-actions.js';
|
|
10
13
|
import { conversationSkills, skillsView } from "./project-skills.js";
|
|
11
14
|
import { readAcceptanceEvidence } from "./chat-acceptance.js";
|
|
@@ -18,6 +21,7 @@ import { cancelCommitment, CHECK_RESULTS, conditionWords, latestResultRun, recor
|
|
|
18
21
|
import { searchMemory } from "./project-memory.js";
|
|
19
22
|
import { integrationsNow, STATE_WORDS } from "./integrations.js";
|
|
20
23
|
import { CAPABILITIES_UNREAD, capabilitiesOf, needsCapabilities } from "./lead-capabilities.js";
|
|
24
|
+
import { feedbackImageProblem } from "./result-actions.js";
|
|
21
25
|
import { readChatResult, reviewInputProblem } from "./chat-review.js";
|
|
22
26
|
import { RESULT_IMAGES_PER_TURN_CAP, selectResultImages } from "./chat-evidence.js";
|
|
23
27
|
import { CHAT_CONTROLS, isChatControl } from "./chat-controls.js";
|
|
@@ -36,7 +40,8 @@ import { CHAT_TASK_ACTIONS, chatTaskRun, chatTaskStamp, isChatTaskAction } from
|
|
|
36
40
|
* projects after scrubbing; full paths and arbitrary text remain redacted.
|
|
37
41
|
*/
|
|
38
42
|
import { Buffer } from "node:buffer";
|
|
39
|
-
import { LEAD_ASK_OTHER } from "./store.js";
|
|
43
|
+
import { LEAD_ASK_OTHER, refArchived } from "./store.js";
|
|
44
|
+
import { releaseFactsOf, tidyDigest, tidyGroups, tidyPreview, TIDY_DEFAULT_DAYS } from "./tidy.js";
|
|
40
45
|
import { hasDisguisedText, hasForbiddenControls } from "./decision.js";
|
|
41
46
|
import { readVerifiedArtifact, scanForSecrets } from "./evidence.js";
|
|
42
47
|
import { parseAcceptanceCriteria } from "./scope.js";
|
|
@@ -377,7 +382,7 @@ export function agentsOver(store, taskId, now) {
|
|
|
377
382
|
* find_tools and advertised from the next request of the same reply.
|
|
378
383
|
*/
|
|
379
384
|
export const LEAD_CORE_TOOLS = new Set([
|
|
380
|
-
"find_tools", "get_brief", "recap", "list_repos", "get_project_context", "search_project_memory", "get_capabilities",
|
|
385
|
+
"find_tools", "get_brief", "recap", "list_repos", "get_project_context", "get_project_activity", "search_project_memory", "get_capabilities",
|
|
381
386
|
"list_tasks", "get_task", "get_result", "get_diff", "get_check_log", "list_decisions", "get_decision",
|
|
382
387
|
"get_actions", "get_action_status", "propose_action", "propose_task", "propose_scope", "propose_steer",
|
|
383
388
|
"propose_answer", "propose_review", "remember", "ask_owner", "commit_to",
|
|
@@ -475,6 +480,15 @@ const LEAD_TOOL_HANDLERS = {
|
|
|
475
480
|
return { ok: true, body: assignmentCatchUp(ctx.store, ctx.now, { principal: 'operator', repos: ctx.who.repos }, repo === null ? {} : { repo }, ctx.evidenceRoot) };
|
|
476
481
|
},
|
|
477
482
|
},
|
|
483
|
+
get_project_activity: {
|
|
484
|
+
description: 'Read project Activity: current Ready backlog, finished-to-decision elapsed time, explicit revisions and recorded cost for completed families in the last 60 days. Includes coverage and a page of underlying tasks (offset: nextOffset for more); not review labor or a quality score.',
|
|
485
|
+
handle: (ctx, args) => {
|
|
486
|
+
const repo = repoPathOf(ctx.who, args['repo']);
|
|
487
|
+
if (!repo || !ctx.store.accountCanAccess(ctx.who.name, repo))
|
|
488
|
+
return { ok: false, message: 'Choose an available project from list_repos.' };
|
|
489
|
+
return { ok: true, body: projectOutcomesPage(projectOutcomes(ctx.store, repo, ctx.now, { principal: 'operator', repos: ctx.who.repos }), Number(args['offset'] ?? 0)) };
|
|
490
|
+
},
|
|
491
|
+
},
|
|
478
492
|
get_project_context: {
|
|
479
493
|
description: 'Find source excerpts or advisory import impact. Read-only; unavailable indexing falls back to source search.',
|
|
480
494
|
handle: (ctx, args) => {
|
|
@@ -656,6 +670,7 @@ const LEAD_TOOL_HANDLERS = {
|
|
|
656
670
|
changes: snippet.slice(0, 1000), changesShortened: snippet.length > 1000,
|
|
657
671
|
verification: ctx.store.proofVerdictFor(snapshot.run)?.verdict ?? "not verified",
|
|
658
672
|
accepted: ctx.store.proofAcceptance(snapshot.run) !== null,
|
|
673
|
+
images: (snapshot.images ?? []).map(one => ({ id: one.artifact, run: one.run })),
|
|
659
674
|
evidenceTool: "get_acceptance_evidence",
|
|
660
675
|
canRevise: snapshot.execution === snapshot.task } };
|
|
661
676
|
},
|
|
@@ -789,7 +804,7 @@ const LEAD_TOOL_HANDLERS = {
|
|
|
789
804
|
},
|
|
790
805
|
},
|
|
791
806
|
propose_review: {
|
|
792
|
-
description: "Read get_result first. revise uses selected saved_notes plus optional note on the SAME task; note saves only. Omitted saved_notes stays untouched.",
|
|
807
|
+
description: "Read get_result first. revise uses selected saved_notes plus optional note on the SAME task; note saves only. Omitted saved_notes stays untouched. To comment on a screenshot, use its image id from get_result_images. If this channel cannot select one, link to the result Comment control and say feedback still needs submitting there.",
|
|
793
808
|
handle: (ctx, args) => {
|
|
794
809
|
const read = ctx.readResults?.get(Number(args["run"]));
|
|
795
810
|
if (read === undefined || read.step >= ctx.step)
|
|
@@ -812,8 +827,20 @@ const LEAD_TOOL_HANDLERS = {
|
|
|
812
827
|
return { ok: false, message: "Write feedback or select saved notes for a revision." };
|
|
813
828
|
if (operation === "revise" && read.snapshot.task !== read.snapshot.execution)
|
|
814
829
|
return { ok: false, message: "A newer revision is current. Read that version before requesting changes." };
|
|
830
|
+
const wanted = args["image"] === null ? undefined : args["image"] ?? (note !== null && ctx.replyImage?.run === read.snapshot.run ? ctx.replyImage.artifact : undefined);
|
|
831
|
+
let image = null;
|
|
832
|
+
if (wanted !== undefined) {
|
|
833
|
+
image = read.snapshot.images?.find(one => one.artifact === wanted) ?? null;
|
|
834
|
+
if (image === null || ctx.evidenceRoot === undefined || note === null)
|
|
835
|
+
return { ok: false, message: "Choose a saved screenshot from the result you read and write feedback." };
|
|
836
|
+
if (ctx.replyImage?.artifact === wanted && !sameFeedbackImage(ctx.replyImage, image))
|
|
837
|
+
return { ok: false, message: "The screenshot you replied to changed. Open the result and select it again." };
|
|
838
|
+
const problem = feedbackImageProblem(ctx.store, ctx.evidenceRoot, read.snapshot.run, image);
|
|
839
|
+
if (problem !== null)
|
|
840
|
+
return { ok: false, message: problem };
|
|
841
|
+
}
|
|
815
842
|
const id = ctx.draft("review", { task: read.snapshot.task, taskTitle: read.snapshot.title, run: read.snapshot.run,
|
|
816
|
-
snapshot: read.snapshot, operation, note, path, line, notes });
|
|
843
|
+
snapshot: read.snapshot, operation, note, path, line, notes, image });
|
|
817
844
|
return id === null ? tooMany() : { ok: true, body: { proposal: id, kind: "review", awaiting: "confirmation", operation } };
|
|
818
845
|
},
|
|
819
846
|
},
|
|
@@ -888,13 +915,19 @@ const LEAD_TOOL_HANDLERS = {
|
|
|
888
915
|
const active = cards.filter(one => one.state === "active"), finished = cards.filter(one => one.state !== "active").slice(-10);
|
|
889
916
|
return { ok: true, body: {
|
|
890
917
|
flow: flow.id, name: flow.name, project: repoIdOf(ctx.who, flow.repo),
|
|
918
|
+
// Browser use (flow-browser.ts), only for a flow whose script zones start one. Names never reach the model.
|
|
919
|
+
...(() => {
|
|
920
|
+
const view = browserViewOf(ctx.store, flow);
|
|
921
|
+
return view === null ? {} : { browser: view.status === "allowed" ? "allowed: its browser zones may start Chromium (turn_off_browser stops it)"
|
|
922
|
+
: `${view.status === "ended" ? "approval ended: the flow or a script changed" : "not allowed"}; its browser zones wait. Propose allow_browser: a person allows it with their own password in the secure screen.` };
|
|
923
|
+
})(),
|
|
891
924
|
steps: definition.stages.map(stage => ({
|
|
892
925
|
id: stage.id, title: stage.title, does: FLOW_KIND_WORDS[stage.kind].label, kind: stage.kind,
|
|
893
926
|
...(stage.instructions === null ? {} : { instructions: stage.instructions.slice(0, 600) }),
|
|
894
927
|
...(stage.kind === "task" ? { planning: stage.planning } : {}),
|
|
895
928
|
...(stage.kind === "approval" ? { decider: stage.toOwner === true ? `the flow's owner (${flow.owner === ctx.who.name ? "you" : "someone else"})` : stage.approver === null ? "anyone who approves" : stage.approver === ctx.who.name ? "you" : "someone else" } : {}),
|
|
896
929
|
...(stage.message === null ? {} : { message: stage.message }),
|
|
897
|
-
...(stage.kind === "check" ? { script: stage.script, scriptExists: stage.script !== null && ctx.store.flowScript(flow.repo, stage.script) !== null } : {}),
|
|
930
|
+
...(stage.kind === "check" ? { script: stage.script, scriptExists: stage.script !== null && ctx.store.flowScript(flow.repo, stage.script) !== null, ...(stage.browser === true ? { startsBrowser: true } : {}) } : {}),
|
|
898
931
|
...(stage.kind === "update" ? { closesIssue: stage.close === true } : {}),
|
|
899
932
|
...(stage.request === undefined ? {} : { method: stage.request.method, url: stage.request.url, headers: Object.keys(stage.request.headers), ...(stage.request.body === null ? {} : { body: stage.request.body.slice(0, 600) }) }),
|
|
900
933
|
...(stage.email === undefined ? {} : { to: stage.email.to, subject: stage.email.subject, body: stage.email.body.slice(0, 600) }),
|
|
@@ -960,7 +993,7 @@ const LEAD_TOOL_HANDLERS = {
|
|
|
960
993
|
},
|
|
961
994
|
},
|
|
962
995
|
propose_flow: {
|
|
963
|
-
description: "Draft a flow change as a card the operator confirms. To make a flow, create with a template or the steps in plain names; leave instructions out unless the operator gave them, and use decider 'me' when they decide. To change one, edit with the whole step list, keeping existing steps by id. For cards use add_card, move_card, approve, send_back with the operator's note, or cancel_card; find the card by what it is about; comment (with @name to ping someone), assign and follow here too. For triage, spam, lead, effort or exception routing, start from the matching template, with the sort as the first step. Use remindAfter and thenMoveTo for follow-ups and decisions that stall. The Issues to PRs template runs GitHub issues labelled toolroll through build, approval, pull request and a comment on the issue. When the operator asks for something to happen every time (fix CI when it fails, turn labelled issues into tasks, queue work overnight, review what went wrong every morning), offer the matching starter; each is one yes, and none merges without a person. When someone new wants a support desk, bug triage, sales follow-up or requests handled, a kit sets up the subagent and its flow in one card. Subagents: propose_subagent adds one (from a template: support, sales, ops, triage), changes one rule section (edit_section), pauses, resumes or removes it, passes it a note, or answers its question for the operator; put it to work with a flow here. When the operator says something like 'Maya can approve refunds up to $100 now', change that section of her soul file; when it's for this week or a one-off, pass it as a note. Subagents use the project's tools under a rule per action (do it, ask first: the operator approves each exact call, never, or up to a limit on a number); propose_subagent use_tool, stop_tool and tool_rule change them, and when a rule has a limit also change the soul file so its words agree. forget or edit_memory when the operator says a subagent has something wrong; a rule change it suggests is a question for the operator, answered only as they say. propose_subagent add_routine puts a card on its desk on a schedule; propose_subagent undo undoes a tool call only when its action has an undo set (tool_rule undoWith). Actions: starter: switch on a starter flow in a project (repo, starter: ci-fix files a fix task when CI fails on the main branch, issue-task makes a task of each GitHub issue labelled toolroll, overnight holds cards added in the day until 22:00 and leaves results for the morning, plane-review reviews the plane's last 24 hours every morning and turns each problem worth fixing into a researched fix and a pull request) — its zones and trigger in one card; offer the matching one when the operator says to do something every time. kit: set up a starter kit in a project (repo, kit: support-desk, bug-triage, sales-follow-up or ops-requests) — a subagent, the flow it works and its buttons, in one card; prefer it when the operator wants a support desk, bug triage, sales follow-up or requests handled. create: a template, or the steps in order (each leads to the next; Done is added; instructions may be left out). 'request' calls a web address (method, url with its host written out, headers — {{secret.NAME}} uses a secret the operator saved on the step, never in chat — and body); 'email' sends mail (to, subject, body; {{card.email}} is the card's email address); 'tool' calls one of the project's tools (server: the tool's name from get_project_tools, tool: its function, args: an object). Put a decision before any of these when they send what a model wrote or what an outsider sent. A 'draft' step has Claude write something from the card (instructions: what to write); follow it with an approval step (decider 'owner' asks the flow's owner in their chat app, where they can approve, edit or send it back), then an 'update' or 'notify' step whose message is '{{stage.<draft id>}}'. A 'sort' step has Jev pick one of its answers; make it the first step (never a holding step before it, or new cards wait unsorted): question, answers (answer, means: a few words Jev reads, goesTo: a step), sureAt (percent, default 80), ifNotSure (a step; otherwise the card waits for a person), and up to 3 alsoNote (score with levels lowest first, or yes-no); a sort has no next, so give each branch's last step its own next. A 'pull-request' step opens a pull request for the card's built result and waits for CI: next when it passes, ifFails when it fails (only this step defaults it: to the build before it, as a revision carrying the failing check); merge ('squash', 'merge' or 'rebase') merges once checks pass, and needs an approval step before it on every path. waitFor 'hours' with from and until (like '22:00' and '06:00') holds cards until the clock is inside those hours. A 'wait' step, after an 'email' step, waits for a reply to that email from someone it went to (waitFor 'reply', the default): next is where a reply goes (the reply is {{stage.<wait id>}}), ifNoReply where the card goes when none comes within wait (like '3 days', up to 30 days); waitFor 'time' just waits, then next. Any step but wait and done can have remindAfter (like '2 days': whoever it waits on is reminded once; 'none' removes it) and, on holding and approval steps, thenMoveTo (a step the card moves to then). subagents (get_subagents): an approval step with subagent (its short name) is decided by that subagent within its rules, and it hands hard ones to the step's decider; a 'subagent' step (subagent, instructions, routes of answer and goesTo) has it read the card, pick where it goes and write what the next steps send (the email body is then {{stage.<id>}}), asking the flow's owner when its rules say to. edit: the full step list, keeping existing steps by id — what a kept step leaves out carries over. add_card (starts in the first zone unless zone is named), move_card, approve, send_back (needs a note), cancel_card, comment (note; @name pings that person), assign (owner: a name, 'me', or 'nobody'), follow, unfollow, save_script (repo, and script: name, about, language python|node|shell, and either body (short) or file (a path in the project, like scripts/enrich.py), and timeoutMinutes; scripts belong to the project, so no flow is needed; a 'check' step in any of its flows names it). A 'check' step runs its script with the card as JSON on stdin (and in $FLOW_INPUT); what it prints is its result for later steps ({{stage.<id>}}); runIn 'folder' (an empty folder: for scripts that work on data) or 'copy' (a copy of the card's work, after setup: for tests on code; the default); routes (answer, goesTo) that a last printed line 'goto: <answer>' picks; ifFails is where a failing script sends the card, such as back to the build (it has no default: without it the card waits there); secrets (names of saved secrets it gets as variables). add_trigger with settings (kind button: label, questions; schedule: schedule like 'daily 09:00 Europe/London', and title, or script (a saved script whose printed items — one per line, a title or JSON with title, description, key — each become a card, once) with secrets; github: repo owner/name, watch issues|pulls|checks, label, branch, from team|anyone; linear: team, state, label; flow: follow (another flow's id), when (its zone); email: folder (default INBOX), sender (addresses or domains), subject (words it must contain); plane-review: at (HH:MM, default 07:30), timeZone — every day it reads the plane's last 24 hours and makes one card per problem worth fixing, a returning problem joining its card); pause_trigger, resume_trigger, remove_trigger with trigger. A 'send' step ('Send to me') sends the card's owner what the step before produced (summary, links, screenshots) in their chat apps, then moves on; a 'choose' step sends the same with 2 to 4 options (label, goesTo: a step, or 'end' to ignore the card) as buttons, ifReplied (where a reply goes as {{note}}; the build before by default), and remindAfter with ifNoReply. choose (card, and choice by number or a note to reply) answers one for the operator. A 'task' step may build in another project: repo (from list_repos). Read get_flows first except to create.",
|
|
996
|
+
description: "Draft a flow change as a card the operator confirms. To make a flow, create with a template or the steps in plain names; leave instructions out unless the operator gave them, and use decider 'me' when they decide. To change one, edit with the whole step list, keeping existing steps by id. For cards use add_card, move_card, approve, send_back with the operator's note, or cancel_card; find the card by what it is about; comment (with @name to ping someone), assign and follow here too. For triage, spam, lead, effort or exception routing, start from the matching template, with the sort as the first step. Use remindAfter and thenMoveTo for follow-ups and decisions that stall. The Issues to PRs template runs GitHub issues labelled toolroll through build, approval, pull request and a comment on the issue. When the operator asks for something to happen every time (fix CI when it fails, turn labelled issues into tasks, queue work overnight, review what went wrong every morning), offer the matching starter; each is one yes, and none merges without a person. When someone new wants a support desk, bug triage, sales follow-up or requests handled, a kit sets up the subagent and its flow in one card. Subagents: propose_subagent adds one (from a template: support, sales, ops, triage), changes one rule section (edit_section), pauses, resumes or removes it, passes it a note, or answers its question for the operator; put it to work with a flow here. When the operator says something like 'Maya can approve refunds up to $100 now', change that section of her soul file; when it's for this week or a one-off, pass it as a note. Subagents use the project's tools under a rule per action (do it, ask first: the operator approves each exact call, never, or up to a limit on a number); propose_subagent use_tool, stop_tool and tool_rule change them, and when a rule has a limit also change the soul file so its words agree. forget or edit_memory when the operator says a subagent has something wrong; a rule change it suggests is a question for the operator, answered only as they say. propose_subagent add_routine puts a card on its desk on a schedule; propose_subagent undo undoes a tool call only when its action has an undo set (tool_rule undoWith). Actions: starter: switch on a starter flow in a project (repo, starter: ci-fix files a fix task when CI fails on the main branch, issue-task makes a task of each GitHub issue labelled toolroll, overnight holds cards added in the day until 22:00 and leaves results for the morning, plane-review reviews the plane's last 24 hours every morning and turns each problem worth fixing into a researched fix and a pull request) — its zones and trigger in one card; offer the matching one when the operator says to do something every time. kit: set up a starter kit in a project (repo, kit: support-desk, bug-triage, sales-follow-up or ops-requests) — a subagent, the flow it works and its buttons, in one card; prefer it when the operator wants a support desk, bug triage, sales follow-up or requests handled. create: a template, or the steps in order (each leads to the next; Done is added; instructions may be left out). 'request' calls a web address (method, url with its host written out, headers — {{secret.NAME}} uses a secret the operator saved on the step, never in chat — and body); 'email' sends mail (to, subject, body; {{card.email}} is the card's email address); 'tool' calls one of the project's tools (server: the tool's name from get_project_tools, tool: its function, args: an object). Put a decision before any of these when they send what a model wrote or what an outsider sent. A 'draft' step has Claude write something from the card (instructions: what to write); follow it with an approval step (decider 'owner' asks the flow's owner in their chat app, where they can approve, edit or send it back), then an 'update' or 'notify' step whose message is '{{stage.<draft id>}}'. A 'sort' step has Jev pick one of its answers; make it the first step (never a holding step before it, or new cards wait unsorted): question, answers (answer, means: a few words Jev reads, goesTo: a step), sureAt (percent, default 80), ifNotSure (a step; otherwise the card waits for a person), and up to 3 alsoNote (score with levels lowest first, or yes-no); a sort has no next, so give each branch's last step its own next. A 'pull-request' step opens a pull request for the card's built result and waits for CI: next when it passes, ifFails when it fails (only this step defaults it: to the build before it, as a revision carrying the failing check); merge ('squash', 'merge' or 'rebase') merges once checks pass, and needs an approval step before it on every path. waitFor 'hours' with from and until (like '22:00' and '06:00') holds cards until the clock is inside those hours. A 'wait' step, after an 'email' step, waits for a reply to that email from someone it went to (waitFor 'reply', the default): next is where a reply goes (the reply is {{stage.<wait id>}}), ifNoReply where the card goes when none comes within wait (like '3 days', up to 30 days); waitFor 'time' just waits, then next. Any step but wait and done can have remindAfter (like '2 days': whoever it waits on is reminded once; 'none' removes it) and, on holding and approval steps, thenMoveTo (a step the card moves to then). subagents (get_subagents): an approval step with subagent (its short name) is decided by that subagent within its rules, and it hands hard ones to the step's decider; a 'subagent' step (subagent, instructions, routes of answer and goesTo) has it read the card, pick where it goes and write what the next steps send (the email body is then {{stage.<id>}}), asking the flow's owner when its rules say to. edit: the full step list, keeping existing steps by id — what a kept step leaves out carries over. add_card (starts in the first zone unless zone is named), move_card, approve, send_back (needs a note), cancel_card, comment (note; @name pings that person), assign (owner: a name, 'me', or 'nobody'), follow, unfollow, save_script (repo, and script: name, about, language python|node|shell, and either body (short) or file (a path in the project, like scripts/enrich.py), and timeoutMinutes; scripts belong to the project, so no flow is needed; a 'check' step in any of its flows names it). A 'check' step runs its script with the card as JSON on stdin (and in $FLOW_INPUT); what it prints is its result for later steps ({{stage.<id>}}); runIn 'folder' (an empty folder: for scripts that work on data) or 'copy' (a copy of the card's work, after setup: for tests on code; the default); routes (answer, goesTo) that a last printed line 'goto: <answer>' picks; ifFails is where a failing script sends the card, such as back to the build (it has no default: without it the card waits there); secrets (names of saved secrets it gets as variables). add_trigger with settings (kind button: label, questions; schedule: schedule like 'daily 09:00 Europe/London', and title, or script (a saved script whose printed items — one per line, a title or JSON with title, description, key — each become a card, once) with secrets; github: repo owner/name, watch issues|pulls|checks, label, branch, from team|anyone; linear: team, state, label; flow: follow (another flow's id), when (its zone); email: folder (default INBOX), sender (addresses or domains), subject (words it must contain); plane-review: at (HH:MM, default 07:30), timeZone — every day it reads the plane's last 24 hours and makes one card per problem worth fixing, a returning problem joining its card); pause_trigger, resume_trigger, remove_trigger with trigger. A 'send' step ('Send to me') sends the card's owner what the step before produced (summary, links, screenshots) in their chat apps, then moves on; a 'choose' step sends the same with 2 to 4 options (label, goesTo: a step, or 'end' to ignore the card) as buttons, ifReplied (where a reply goes as {{note}}; the build before by default), and remindAfter with ifNoReply. choose (card, and choice by number or a note to reply) answers one for the operator. A 'task' step may build in another project: repo (from list_repos). Read get_flows first except to create. allow_browser (flow): when get_flows says a flow's browser zones wait, propose allowing them to start Chromium; the operator allows it with their own password in the secure screen, never on the card. turn_off_browser (flow) stops it.",
|
|
964
997
|
// An edit's kept steps may leave their kind and name to the zone they keep: they are filled in before the call is read.
|
|
965
998
|
prepare: (ctx, given) => {
|
|
966
999
|
const editing = given["operation"] === "edit" && Number.isSafeInteger(given["flow"]) ? ctx.store.getFlow(Number(given["flow"])) : null;
|
|
@@ -1100,7 +1133,16 @@ const LEAD_TOOL_HANDLERS = {
|
|
|
1100
1133
|
operation = "flow_trigger_remove";
|
|
1101
1134
|
input = pick(["trigger"]);
|
|
1102
1135
|
break;
|
|
1103
|
-
|
|
1136
|
+
// Browser use in the flow's script zones: a proposal only; the person allows it with their own password.
|
|
1137
|
+
case "allow_browser":
|
|
1138
|
+
operation = "flow_browser";
|
|
1139
|
+
input = pick(["flow"]);
|
|
1140
|
+
break;
|
|
1141
|
+
case "turn_off_browser":
|
|
1142
|
+
operation = "flow_browser_off";
|
|
1143
|
+
input = pick(["flow"]);
|
|
1144
|
+
break;
|
|
1145
|
+
default: return { ok: false, message: "Choose create, edit, add_card, move_card, approve, send_back, cancel_card, comment, assign, follow, unfollow, add_trigger, pause_trigger, resume_trigger, remove_trigger, allow_browser or turn_off_browser." };
|
|
1104
1146
|
}
|
|
1105
1147
|
const action = prepareSharedAction(ctx.store, ctx.who, operation, input, ctx.evidenceRoot, ctx.now);
|
|
1106
1148
|
const id = ctx.draft("action", { ...action });
|
|
@@ -1497,7 +1539,8 @@ const LEAD_TOOL_HANDLERS = {
|
|
|
1497
1539
|
const integrations = list.map(one => ({
|
|
1498
1540
|
name: one.name, kind: one.group, state: STATE_WORDS[one.state], account: one.account, detail: one.detail, usedBy: one.usedBy,
|
|
1499
1541
|
lastSuccessAt: one.lastSuccessAt, lastError: one.lastError,
|
|
1500
|
-
next: one.action.kind === "setup" ? "Not set up: open Settings → Integrations to set it up" : one.action.kind === "fix" ? `Fix: ${one.action.words}`
|
|
1542
|
+
next: one.action.kind === "setup" ? "Not set up: open Settings → Integrations to set it up" : one.action.kind === "fix" ? `Fix: ${one.action.words}`
|
|
1543
|
+
: one.action.kind === "switch" ? (one.action.words !== null ? `Fix: ${one.action.words}` : one.action.on ? "Turned off: turn it on in Settings → Integrations" : null) : null,
|
|
1501
1544
|
}));
|
|
1502
1545
|
return { ok: true, body: { integrations, settings: "show_control integrations opens Settings → Integrations; never invent a link" } };
|
|
1503
1546
|
},
|
|
@@ -1582,11 +1625,12 @@ const LEAD_TOOL_HANDLERS = {
|
|
|
1582
1625
|
return { ok: false, message: "search needs a word that names the work, such as a page, feature or file" };
|
|
1583
1626
|
// A search reads further back than the newest page, then ranks by how many of the words each task's title and goal hold.
|
|
1584
1627
|
const listed = ctx.store.taskFamiliesAdmitted(repo === null ? ctx.who.repos : [repo], false, { limit: words.length === 0 ? limit + 1 : SEARCH_FAMILIES, order: words.length === 0 ? "created" : "updated", ...(args["state"] === undefined ? {} : { states: [args["state"]] }) });
|
|
1585
|
-
|
|
1628
|
+
// A put-away task (v145) is out of every list, the lead's included.
|
|
1629
|
+
const families = (words.length === 0 ? listed : listed
|
|
1586
1630
|
.map((one, index) => ({ one, index, hits: searchHits(words, [one.root.id, one.root.title, one.current.title, ctx.store.getScope(one.current.id)?.goal ?? "", ctx.store.getScope(one.root.id)?.goal ?? ""]) }))
|
|
1587
1631
|
.filter(match => match.hits > 0)
|
|
1588
1632
|
.sort((a, b) => b.hits - a.hits || a.index - b.index)
|
|
1589
|
-
.map(match => match.one);
|
|
1633
|
+
.map(match => match.one)).filter(one => !refArchived(ctx.store, one.current.refId));
|
|
1590
1634
|
const tasks = families.slice(0, limit).map(one => ({
|
|
1591
1635
|
repo: `r${ctx.who.repos.indexOf(one.current.repo) + 1}`, task: one.root.id, execution: one.current.id,
|
|
1592
1636
|
title: one.root.title, state: one.current.state, historyProblem: one.problem, otherActive: one.otherActive.map(version => version.id),
|
|
@@ -1596,6 +1640,17 @@ const LEAD_TOOL_HANDLERS = {
|
|
|
1596
1640
|
return { ok: true, body: { tasks, truncated: families.length > limit } };
|
|
1597
1641
|
},
|
|
1598
1642
|
},
|
|
1643
|
+
tidy_preview: {
|
|
1644
|
+
description: "Read-only: what Put away old tasks would put away now and why, grouped (old releases, old routine runs, resolved CI notices, finished more than `days` days ago, default 14). Only a person puts tasks away; you can't.",
|
|
1645
|
+
handle: (ctx, args) => {
|
|
1646
|
+
const days = typeof args["days"] === "number" ? args["days"] : TIDY_DEFAULT_DAYS;
|
|
1647
|
+
const items = tidyPreview(ctx.store, ctx.now, { releases: releaseFactsOf(ctx.store), days, access: { principal: "operator", repos: ctx.who.repos, includeUnplaced: false } });
|
|
1648
|
+
const digest = tidyDigest(items, days);
|
|
1649
|
+
return { ok: true, body: { count: items.length, days, digest,
|
|
1650
|
+
groups: tidyGroups(items, days).map(group => ({ label: group.label, tasks: group.items.map(one => ({ task: one.taskId, title: one.title, why: one.reason })) })),
|
|
1651
|
+
apply: items.length === 0 ? "Nothing to put away." : `A person puts these away: Tasks → Put away old tasks, or \`toolroll task tidy --apply --digest ${digest}${days === TIDY_DEFAULT_DAYS ? "" : ` --days ${days}`}\`.` } };
|
|
1652
|
+
},
|
|
1653
|
+
},
|
|
1599
1654
|
get_task: {
|
|
1600
1655
|
description: "Read currentExecution, state, dispatch, history, scope, dependencies, holds, queue, attempts, decisions and whether the agent has read your notes before acting.",
|
|
1601
1656
|
handle: (ctx, args) => {
|
package/dist/lead-voice.js
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
import { actorLabel, withActor } from "./actor.js";
|
|
9
9
|
import { chatControlHref } from "./chat-controls.js";
|
|
10
10
|
import { BATCH_MS, chatText, chatTitle } from "./chat-voice.js";
|
|
11
|
-
import { BUILT_IN } from "./store.js";
|
|
11
|
+
import { BUILT_IN, refArchived } from "./store.js";
|
|
12
12
|
import { leadNameOf } from "./lead-identity.js";
|
|
13
13
|
import { leadLapsed } from "./task-status.js";
|
|
14
14
|
import { phoneText as plain } from "./telegram-status.js";
|
|
@@ -85,19 +85,24 @@ export function leadSay(store, actor, text, taskId, now) {
|
|
|
85
85
|
// The task's own id never reaches a chat: it reads as the task's short title (chat-voice.ts).
|
|
86
86
|
const said = taskId === null ? text.trim() : chatText(text.trim(), [{ id: taskId, title: chatTitle(store, taskId) }]);
|
|
87
87
|
return store.transact(() => {
|
|
88
|
+
// A put-away task (v145) gets no messages: the lead's words about it would nudge a person about nothing.
|
|
89
|
+
if (task !== null && refArchived(store, task.refId))
|
|
90
|
+
return { ok: false, reason: "refused", message: "This task is put away. A person can restore it first." };
|
|
88
91
|
const stamp = now.toISOString();
|
|
89
92
|
const ledger = store.recordAction({ at: stamp, actor: actorLabel(actor), repo: task?.repo ?? null, taskId, runId: null,
|
|
90
93
|
action: LEAD_SAID, outcome: "recorded", source: "work", detail: text.trim() });
|
|
91
|
-
const open = store.handle.prepare(`SELECT id, dedupe_key, body FROM notification WHERE kind = ? AND recipient = ? ORDER BY id DESC LIMIT 1`)
|
|
94
|
+
const open = store.handle.prepare(`SELECT id, dedupe_key, body, task_ref FROM notification WHERE kind = ? AND recipient = ? ORDER BY id DESC LIMIT 1`)
|
|
92
95
|
.get(LEAD_SAY_KIND, actor.account);
|
|
93
96
|
const opened = open === undefined ? null : /^lead-say:(.+):\d+$/.exec(String(open["dedupe_key"]))?.[1] ?? null;
|
|
94
|
-
|
|
97
|
+
// A batch is about one task (or none): words about another start a row of their own, so each row keeps its task.
|
|
98
|
+
const sameTask = open !== undefined && (open["task_ref"] ?? null) === (task === null ? null : task.refId);
|
|
99
|
+
const joined = sameTask && opened !== null && Date.parse(opened) > now.getTime() - BATCH_MS && Date.parse(opened) <= now.getTime();
|
|
95
100
|
const lines = [...(joined ? String(open["body"]).split("\n") : []), said].slice(-BATCH_LINES);
|
|
96
101
|
if (joined)
|
|
97
102
|
store.handle.prepare("UPDATE notification SET resolved_at = ? WHERE id = ? AND resolved_at IS NULL").run(stamp, Number(open["id"]));
|
|
98
103
|
const key = `lead-say:${joined ? opened : stamp}:${ledger}`;
|
|
99
104
|
store.enqueueNotification({ dedupeKey: key, kind: LEAD_SAY_KIND, subject: leadNameOf(store, actor.account), body: lines.join("\n"),
|
|
100
|
-
recipient: actor.account, source: { installation: true }, ...(taskId === null ? {} : { link: chatControlHref("task", taskId) }) }, now);
|
|
105
|
+
recipient: actor.account, source: task === null ? { installation: true } : { taskRef: task.refId }, ...(taskId === null ? {} : { link: chatControlHref("task", taskId) }) }, now);
|
|
101
106
|
const row = store.handle.prepare("SELECT id FROM notification WHERE dedupe_key = ?").get(key);
|
|
102
107
|
return { ok: true, joined, notification: row === undefined ? null : Number(row["id"]) };
|
|
103
108
|
});
|
|
@@ -136,14 +141,20 @@ export function leadClaim(store, actor, taskId, now) {
|
|
|
136
141
|
if ("ok" in task)
|
|
137
142
|
return task;
|
|
138
143
|
const { root } = familyOf(store, taskId);
|
|
139
|
-
store.transact(() => {
|
|
144
|
+
const taken = store.transact(() => {
|
|
145
|
+
// A put-away task (v145) waits on nobody, so the lead takes nothing on there: checked with the claim's own write.
|
|
146
|
+
if (refArchived(store, task.refId))
|
|
147
|
+
return false;
|
|
140
148
|
const ledger = store.recordAction({ at: now.toISOString(), actor: actorLabel(actor), repo: task.repo, taskId: root, runId: null,
|
|
141
149
|
action: LEAD_CLAIMED, outcome: "recorded", source: "work" });
|
|
142
150
|
// The owner's card for this task repaints to "<name> is on it": quiet chat edits its card, and every-update
|
|
143
151
|
// chat edits the attempt's own card (the Failed alert), or follows it up when that message is gone.
|
|
144
152
|
store.enqueueNotification({ dedupeKey: `lead-on-it:${ledger}`, kind: LEAD_ON_IT_KIND, subject: `${leadNameOf(store, actor.account)} is on it`, body: "",
|
|
145
153
|
link: chatControlHref("task", taskId), source: cardSource(store, root) ?? { taskRef: task.refId } }, now);
|
|
154
|
+
return true;
|
|
146
155
|
});
|
|
156
|
+
if (!taken)
|
|
157
|
+
return { ok: false, reason: "refused", message: "This task is put away. A person can restore it first." };
|
|
147
158
|
return { ok: true, root, claim: leadClaimOf(store, taskId, now, actor.account) };
|
|
148
159
|
}
|
|
149
160
|
/** Where a task's chat card lives: the family's newest attempt (the card every-update chat edits), else its newest
|
package/dist/lead.d.ts
CHANGED
|
@@ -38,6 +38,8 @@ export type LeadTurnInput = {
|
|
|
38
38
|
* visible thread so a task-scoped composer still reads like a normal
|
|
39
39
|
* conversation. */
|
|
40
40
|
context?: string;
|
|
41
|
+
/** Exact image from the transport record of the message being answered. */
|
|
42
|
+
replyImage?: import("./result-review.js").FeedbackImage;
|
|
41
43
|
fetcher?: typeof fetch;
|
|
42
44
|
/** Injected by tests; production invokes the isolated local harness. */
|
|
43
45
|
subscriptionRunner?: SubscriptionLeadRunner;
|
package/dist/lead.js
CHANGED
|
@@ -110,7 +110,7 @@ function settleBy(work, ms) {
|
|
|
110
110
|
const late = new Promise(resolve => { timer = setTimeout(() => resolve(LATE), Math.max(0, ms)); });
|
|
111
111
|
return Promise.race([work, late]).finally(() => clearTimeout(timer));
|
|
112
112
|
}
|
|
113
|
-
const READ_TOOLS = new Set(["get_brief", "get_project_context", "get_actions", "get_action_status", "get_skills", "get_acceptance_evidence", "recap", "list_repos", "list_tasks", "get_task", "get_result", "get_result_images", "get_controls", "get_agents", "get_project_knowledge", "get_task_conversation", "get_diff", "get_check_log", "get_project_tools", "get_flows", "get_flow_insights", "list_decisions", "get_decision", "queue"]);
|
|
113
|
+
const READ_TOOLS = new Set(["get_brief", "get_project_context", "get_project_activity", "get_actions", "get_action_status", "get_skills", "get_acceptance_evidence", "recap", "list_repos", "list_tasks", "get_task", "get_result", "get_result_images", "get_controls", "get_agents", "get_project_knowledge", "get_task_conversation", "get_diff", "get_check_log", "get_project_tools", "get_flows", "get_flow_insights", "list_decisions", "get_decision", "queue"]);
|
|
114
114
|
/** The last messages of the thread as provider-neutral history, newest kept first until the byte cap. */
|
|
115
115
|
export function historyFor(store, thread, queuedMessageId, named = queuedMessageId !== undefined) {
|
|
116
116
|
// Admitted messages only (v128): a queued message — this one, a teammate's, or one removed while waiting — never
|
|
@@ -205,7 +205,7 @@ export async function runLeadTurn(input) {
|
|
|
205
205
|
return refuse("thread-closed");
|
|
206
206
|
if (liveSession.ceilingDigest !== who.ceilingDigest || liveThread.ceilingDigest !== who.ceilingDigest)
|
|
207
207
|
return refuse("ceiling-changed");
|
|
208
|
-
const digest = createHash("sha256").update(JSON.stringify([thread.id, message, input.context ?? null])).digest("hex");
|
|
208
|
+
const digest = createHash("sha256").update(JSON.stringify([thread.id, message, input.context ?? null, ...(input.replyImage === undefined ? [] : [input.replyImage])])).digest("hex");
|
|
209
209
|
const receipt = request === undefined ? null : store.leadRequestReceipt(session.id, request);
|
|
210
210
|
if (receipt !== null)
|
|
211
211
|
return receipt.digest === digest ? { ok: true, replayed: true, turn: receipt.turn } : refuse("request-changed");
|
|
@@ -568,7 +568,7 @@ export async function runLeadTurn(input) {
|
|
|
568
568
|
// caller of executeLeadTool): the model learns the road (find_tools, then the next step) and the reply goes on.
|
|
569
569
|
const outcome = !advertisedNames.has(call.name)
|
|
570
570
|
? { ok: false, message: `${call.name} isn't available in this step. Call find_tools with what you want to do; tools it finds can be called from your next step.` }
|
|
571
|
-
: executeLeadTool({ store, who, now: clock(), draft, selectEvidence, step: steps, readDecisions, readResults, searchedMemory, checkedCapabilities, ask, findTools, ...(input.integrations === undefined ? {} : { integrations: input.integrations }), thread: thread.id, turn: turnId, ...(promiseChannelOfTurn(input.channel) === undefined ? {} : { channel: promiseChannelOfTurn(input.channel) }), ...(input.evidenceRoot === undefined ? {} : { evidenceRoot: input.evidenceRoot }), ...(input.mediaDelivery === undefined ? {} : { mediaDelivery: input.mediaDelivery }) }, call.name, call.args, view);
|
|
571
|
+
: executeLeadTool({ store, who, now: clock(), draft, selectEvidence, ...(input.replyImage === undefined ? {} : { replyImage: input.replyImage }), step: steps, readDecisions, readResults, searchedMemory, checkedCapabilities, ask, findTools, ...(input.integrations === undefined ? {} : { integrations: input.integrations }), thread: thread.id, turn: turnId, ...(promiseChannelOfTurn(input.channel) === undefined ? {} : { channel: promiseChannelOfTurn(input.channel) }), ...(input.evidenceRoot === undefined ? {} : { evidenceRoot: input.evidenceRoot }), ...(input.mediaDelivery === undefined ? {} : { mediaDelivery: input.mediaDelivery }) }, call.name, call.args, view);
|
|
572
572
|
let displayOutcome = { state: "succeeded" };
|
|
573
573
|
if (!outcome.ok) {
|
|
574
574
|
const reason = leadToolFailureReason(call.name, outcome.message);
|
package/dist/operate.d.ts
CHANGED
|
@@ -99,7 +99,7 @@ export type OperateOptions = {
|
|
|
99
99
|
/** Injected by tests: how the console looks at project folders off its thread (folder-look.ts). */
|
|
100
100
|
folderLook?: FolderLookOptions;
|
|
101
101
|
};
|
|
102
|
-
export type OnboardSeams = Partial<Pick<OnboardIo, "home" | "env" | "cwd" | "interactive" | "confirm" | "findRepo" | "checkConnection" | "pullRequests">>;
|
|
102
|
+
export type OnboardSeams = Partial<Pick<OnboardIo, "home" | "env" | "cwd" | "interactive" | "confirm" | "findRepo" | "checkConnection" | "pullRequests" | "youiyoux">>;
|
|
103
103
|
export declare const OPERATE_HELP: string;
|
|
104
104
|
/** Parsed flags, with the positionals left over. */
|
|
105
105
|
type Args = {
|
|
@@ -115,7 +115,7 @@ type Args = {
|
|
|
115
115
|
* exports are behavior, not commentary — and the declared command guide
|
|
116
116
|
* (surface.ts) is tested for exact equality against them.
|
|
117
117
|
*/
|
|
118
|
-
export declare const TASK_ACTIONS: readonly ["add", "list", "show", "wait", "state", "block", "unblock", "next", "steer", "pause", "continue", "assign", "reopen", "scope", "approve", "hold", "unhold", "require", "requeue", "regate", "plan", "review", "accept", "repair", "route", "stop", "resume", "complete", "revise", "merge", "ask", "checks", "add-tests"];
|
|
118
|
+
export declare const TASK_ACTIONS: readonly ["add", "list", "show", "wait", "state", "block", "unblock", "next", "steer", "pause", "continue", "assign", "reopen", "scope", "approve", "hold", "unhold", "require", "requeue", "regate", "plan", "review", "accept", "repair", "route", "stop", "resume", "complete", "revise", "merge", "ask", "checks", "add-tests", "archive", "restore", "tidy"];
|
|
119
119
|
export declare const PUBLISH_ACTIONS: readonly ["setup", "grant", "revoke", "status", "unblock", "rearm", "merge", "refire"];
|
|
120
120
|
export declare const CONFIG_ACTIONS: readonly ["show", "set", "clear"];
|
|
121
121
|
export declare const APPROVER_ACTIONS: readonly ["list", "add"];
|
|
@@ -237,7 +237,6 @@ type Context = {
|
|
|
237
237
|
export declare function writeLoginFileDurably(path: string, name: string, password: string): void;
|
|
238
238
|
/** The platform browser opener — detached, silent, never load-bearing. */
|
|
239
239
|
export declare function openBrowser(url: string): void;
|
|
240
|
-
export declare function readUpConsoleUrl(dir: string): string | null;
|
|
241
240
|
/**
|
|
242
241
|
* The people allowed to agree to a scope.
|
|
243
242
|
*
|