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/surface.js
CHANGED
|
@@ -171,7 +171,7 @@ const GUIDE_ROWS = [
|
|
|
171
171
|
notableReasons: ["no-result"] },
|
|
172
172
|
{ invocation: "task list", synopsis: "a page of saved task status", audience: "agent", agentMayInvoke: true, mutation: "none",
|
|
173
173
|
flags: [jsonFlag, dbFlag, { name: "state", takesValue: true, meaning: "queued|running|done|failed|cancelled" },
|
|
174
|
-
{ name: "view", takesValue: true, meaning: "all|needs-you|running|completed" },
|
|
174
|
+
{ name: "view", takesValue: true, meaning: "all|needs-you|running|completed|archived" },
|
|
175
175
|
{ name: "limit", takesValue: true, meaning: "page size, 1–100; default 40" },
|
|
176
176
|
{ name: "cursor", takesValue: true, meaning: "nextCursor from the previous response" },
|
|
177
177
|
{ name: "repo", takesValue: true, meaning: "filter to one project" }] },
|
|
@@ -299,6 +299,18 @@ const GUIDE_ROWS = [
|
|
|
299
299
|
operator("task route", "which configured agents plan, build and repair this task; phase and size changes require renewed approval"),
|
|
300
300
|
operator("task reopen", "resume external work its tracker closed and has been SEEN open again"),
|
|
301
301
|
operator("task stop", "stop ONE exact live attempt (--run <id>): durable before any process is signalled, answers 'stopping' until its own processes are established gone; work, branch, and evidence preserved; no strike, no retry"),
|
|
302
|
+
{ ...operator("task archive", "put tasks away (a person's act): out of every list, count and nudge, history and approvals kept; nothing claims, approves or dispatches them until restored"),
|
|
303
|
+
positionals: [{ name: "id", required: true, meaning: "one or more tasks (any version: the whole family goes)" }],
|
|
304
|
+
flags: [jsonFlag, dbFlag, { name: "reason", takesValue: true, meaning: "why, shown on the task page" }], notableReasons: ["unknown-task", "not-an-approver"] },
|
|
305
|
+
{ ...operator("task restore", "bring put-away tasks back exactly as they were (a person's act)"),
|
|
306
|
+
positionals: [{ name: "id", required: true, meaning: "one or more put-away tasks" }], flags: [jsonFlag, dbFlag], notableReasons: ["unknown-task", "not-an-approver"] },
|
|
307
|
+
{ ...operator("task tidy", "Put away old tasks: --preview lists what would go and why (read-only), --apply --digest <d> puts away exactly that list (a person's act)"),
|
|
308
|
+
flags: [jsonFlag, dbFlag, { name: "preview", takesValue: false, meaning: "show the list and the digest; changes nothing" },
|
|
309
|
+
{ name: "apply", takesValue: false, meaning: "put away exactly the previewed list (needs --digest)" },
|
|
310
|
+
{ name: "digest", takesValue: true, meaning: "the digest --preview printed" },
|
|
311
|
+
{ name: "days", takesValue: true, meaning: "also finished tasks untouched this many days (1–365, default 14)" },
|
|
312
|
+
{ name: "except", takesValue: true, meaning: "comma-separated tasks from the list to leave out" }],
|
|
313
|
+
notableReasons: ["usage", "not-an-approver", "empty"] },
|
|
302
314
|
operator("run settle", "last resort for a finished run whose process witness can't be proven either way: records your --why in the ledger; refuses while any of the run's processes is alive"),
|
|
303
315
|
operator("task resume", "resume the exact stopped attempt (--run <id>): refuses until it is quiescent, lifts only that stop's hold, approves nothing — the next pass re-proves the scope and inherits the draft with fresh proof"),
|
|
304
316
|
// ---- leases (runner surface) ----
|
|
@@ -443,11 +455,15 @@ const REMOTE_NO = [
|
|
|
443
455
|
"enroll", "revoke",
|
|
444
456
|
// Flow steps that fetch addresses or run checks and scripts here.
|
|
445
457
|
"flows import", "flows trigger check", "flows script save",
|
|
458
|
+
// Lets a flow script on this machine start Chromium in its sandbox: a person here, with their own password.
|
|
459
|
+
"flows browser",
|
|
446
460
|
// Reads this machine owner's own Claude and Codex session files (~/.claude, ~/.codex).
|
|
447
461
|
"memory propose",
|
|
448
462
|
];
|
|
449
463
|
const REMOTE_STEP_UP = [
|
|
450
|
-
"proposals", "decide", "task regate", "task approve", "task accept", "task merge", "run settle",
|
|
464
|
+
"proposals", "decide", "task regate", "task approve", "task accept", "task merge", "run settle",
|
|
465
|
+
// Putting tasks away and restoring them: a person's act, in the console or on the server's machine.
|
|
466
|
+
"task archive", "task restore", "task tidy", "knowledge apply", "memory apply",
|
|
451
467
|
"flows card approve", "flows card send-back", "flows script approve", "flows unattended",
|
|
452
468
|
"approver list", "approver add", "people list", "people invite", "people projects", "people revoke",
|
|
453
469
|
// A person's own API tokens: a password step-up on the server's machine, or the console. Never with a token.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/** Put-away checks (v145, docs/plans/task-tidy.md), in a leaf module so every door can ask without loading the store. */
|
|
2
|
+
import type { Store } from "./store.js";
|
|
3
|
+
/** Whether this task version is put away. Every door that dispatches, claims or approves asks this (fail closed: a
|
|
4
|
+
* row means no). */
|
|
5
|
+
export declare function refArchived(store: Store, taskRef: number): boolean;
|
|
6
|
+
/** Whether the built-in task with this id is put away. */
|
|
7
|
+
export declare function taskArchived(store: Store, taskId: string): boolean;
|
|
8
|
+
/** Whether a flow card's work is put away: its current task or its first build task (a later stage keeps the first
|
|
9
|
+
* and may clear the current one). Read from the card's own row now, so a put away that committed first holds it. */
|
|
10
|
+
export declare function cardTaskArchived(store: Store, cardId: number): boolean;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/** Whether this task version is put away. Every door that dispatches, claims or approves asks this (fail closed: a
|
|
2
|
+
* row means no). */
|
|
3
|
+
export function refArchived(store, taskRef) {
|
|
4
|
+
return store.handle.prepare("SELECT 1 FROM task_archive WHERE task_ref = ?").get(taskRef) !== undefined;
|
|
5
|
+
}
|
|
6
|
+
/** Whether the built-in task with this id is put away. */
|
|
7
|
+
export function taskArchived(store, taskId) {
|
|
8
|
+
return store.handle.prepare(`SELECT 1 FROM task_archive a JOIN task_ref r ON r.id = a.task_ref
|
|
9
|
+
WHERE r.backend = 'built-in' AND r.external_id = ?`).get(taskId) !== undefined;
|
|
10
|
+
}
|
|
11
|
+
/** Whether a flow card's work is put away: its current task or its first build task (a later stage keeps the first
|
|
12
|
+
* and may clear the current one). Read from the card's own row now, so a put away that committed first holds it. */
|
|
13
|
+
export function cardTaskArchived(store, cardId) {
|
|
14
|
+
return store.handle.prepare(`SELECT 1 FROM flow_card c JOIN task_ref r ON r.backend = 'built-in' AND r.external_id IN (c.task, c.primary_task)
|
|
15
|
+
JOIN task_archive a ON a.task_ref = r.id WHERE c.id = ?`).get(cardId) !== undefined;
|
|
16
|
+
}
|
package/dist/task-control.d.ts
CHANGED
|
@@ -102,7 +102,7 @@ export type ResumeOutcome = {
|
|
|
102
102
|
gate: DispatchDiagnosis | null;
|
|
103
103
|
} | {
|
|
104
104
|
ok: false;
|
|
105
|
-
reason: "no-task" | "no-stop" | "wrong-task" | "stopping" | "already-resumed" | "superseded" | "busy" | "review" | "occupied";
|
|
105
|
+
reason: "no-task" | "no-stop" | "wrong-task" | "stopping" | "already-resumed" | "superseded" | "busy" | "review" | "occupied" | "archived";
|
|
106
106
|
detail: string;
|
|
107
107
|
};
|
|
108
108
|
/**
|
package/dist/task-source.d.ts
CHANGED
|
@@ -51,8 +51,20 @@ export type TaskOrigin = {
|
|
|
51
51
|
url: string | null;
|
|
52
52
|
host: string | null;
|
|
53
53
|
} | null;
|
|
54
|
+
/** A youiyoux change or options request (youiyoux-intake.ts): its id, its kind, and where the person pointed. */
|
|
55
|
+
request?: {
|
|
56
|
+
id: string;
|
|
57
|
+
kind: "change" | "options";
|
|
58
|
+
route: string | null;
|
|
59
|
+
component: string | null;
|
|
60
|
+
at: string | null;
|
|
61
|
+
} | null;
|
|
54
62
|
};
|
|
55
|
-
/** A task's origin, or null when it came from neither a flow
|
|
63
|
+
/** A task's origin, or null when it came from neither a flow, an outside event nor a youiyoux request. */
|
|
56
64
|
export declare function originOf(store: Store, taskId: string, canSee: (repo: string) => boolean): TaskOrigin | null;
|
|
65
|
+
/** A youiyoux request by its kind: "youiyoux change request r-…" or "youiyoux options request r-…". */
|
|
66
|
+
export declare function requestName(request: NonNullable<TaskOrigin["request"]>): string;
|
|
67
|
+
/** Where a youiyoux request pointed, in words: "Button on /flows (src/button.tsx:12)". */
|
|
68
|
+
export declare function requestWords(request: NonNullable<TaskOrigin["request"]>): string;
|
|
57
69
|
/** The one line an approval shows about an outside event that started its work: context, never a term agreed to. */
|
|
58
70
|
export declare function originNote(origin: TaskOrigin | null | undefined): string | null;
|
package/dist/task-source.js
CHANGED
|
@@ -71,8 +71,11 @@ export function cardReference(source) {
|
|
|
71
71
|
const snapshot = snapshotOf(source ?? null);
|
|
72
72
|
return snapshot === null ? "" : referenceWords(snapshot);
|
|
73
73
|
}
|
|
74
|
-
/** A task's origin, or null when it came from neither a flow
|
|
74
|
+
/** A task's origin, or null when it came from neither a flow, an outside event nor a youiyoux request. */
|
|
75
75
|
export function originOf(store, taskId, canSee) {
|
|
76
|
+
const request = store.youiyouxOriginOf(taskId);
|
|
77
|
+
if (request !== null)
|
|
78
|
+
return { flow: null, source: null, request: { id: request.request, kind: request.kind, route: request.route, component: request.component, at: request.at } };
|
|
76
79
|
const kept = store.taskSourceOf(taskId);
|
|
77
80
|
const flowId = kept?.flow ?? Number(/^flow:(\d+)$/.exec(store.filedViaOf(taskId) ?? "")?.[1] ?? NaN);
|
|
78
81
|
const snapshot = kept === null ? null : readSnapshot(kept.sourceJson);
|
|
@@ -84,8 +87,21 @@ export function originOf(store, taskId, canSee) {
|
|
|
84
87
|
source: snapshot === null ? null : { label: snapshot.label, proved: provedWords(snapshot), url: snapshot.external.url, host: hostOf(snapshot.external.url) },
|
|
85
88
|
};
|
|
86
89
|
}
|
|
90
|
+
/** A youiyoux request by its kind: "youiyoux change request r-…" or "youiyoux options request r-…". */
|
|
91
|
+
export function requestName(request) {
|
|
92
|
+
return `youiyoux ${request.kind === "options" ? "options" : "change"} request ${request.id}`;
|
|
93
|
+
}
|
|
94
|
+
/** Where a youiyoux request pointed, in words: "Button on /flows (src/button.tsx:12)". */
|
|
95
|
+
export function requestWords(request) {
|
|
96
|
+
const what = [request.component, request.route === null ? null : `on ${request.route}`].filter(one => one !== null).join(" ");
|
|
97
|
+
return `${what === "" ? "" : what}${request.at === null ? "" : `${what === "" ? "" : " "}(${request.at})`}`;
|
|
98
|
+
}
|
|
87
99
|
/** The one line an approval shows about an outside event that started its work: context, never a term agreed to. */
|
|
88
100
|
export function originNote(origin) {
|
|
101
|
+
if (origin?.request != null) {
|
|
102
|
+
const where = requestWords(origin.request);
|
|
103
|
+
return `From ${requestName(origin.request)}${where === "" ? "" : `: ${where}`}. Whoever can write the project's folder wrote these words; read them all before you approve.`;
|
|
104
|
+
}
|
|
89
105
|
if (origin?.source == null)
|
|
90
106
|
return null;
|
|
91
107
|
const where = origin.source.host === null ? "" : ` · ${origin.source.host}`;
|
package/dist/telegram-lead.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { CHAT_ACTIONS, sharedActionAllowsChallenge, sharedActionPayload } from "./chat-actions.js";
|
|
2
|
-
import { taskInCeiling, mirrorToTaskChat, couldNotAnswerText, channelRepos as telegramConversationRepos, resolveChannelLead as resolveTelegramLead, NO_PHONE_LINK, NO_TASK_LINK,
|
|
2
|
+
import { taskInCeiling, mirrorToTaskChat, couldNotAnswerText, channelRepos as telegramConversationRepos, resolveChannelLead as resolveTelegramLead, NO_PHONE_LINK, NO_TASK_LINK, phoneProposalLink, confirmedLink, phoneProposalPreview, proposalOutcomeText, handoffCardText, confirmedCardText } from "./chat-channel.js";
|
|
3
3
|
export { channelRepos as telegramConversationRepos, resolveChannelLead as resolveTelegramLead, tooLongText, whichTaskText, replyContextFor, NO_PHONE_LINK, NO_TASK_LINK, proposalLink, confirmedLink, proposalPreview, proposalOutcomeText, handoffCardText, confirmedCardText, CHAT_ACTION_PARITY as TELEGRAM_ACTION_PARITY, parityGaps } from "./chat-channel.js";
|
|
4
4
|
/**
|
|
5
5
|
* The paired phone as one more way to use the same assistant.
|
|
@@ -207,7 +207,7 @@ export function applyProposalTap(store, binding, token, message, repos, options,
|
|
|
207
207
|
return { effects, confirmed: false, ignored: true };
|
|
208
208
|
}
|
|
209
209
|
const who = verified.who;
|
|
210
|
-
const preview =
|
|
210
|
+
const preview = phoneProposalPreview(store, proposal, actionRepos);
|
|
211
211
|
const origin = options.phoneOrigin?.() ?? null;
|
|
212
212
|
if (preview.closed) {
|
|
213
213
|
store.consumeTelegramProposalActions(proposal.id, now);
|
|
@@ -239,7 +239,7 @@ export function applyProposalTap(store, binding, token, message, repos, options,
|
|
|
239
239
|
// A forged keyboard on a handoff card: nothing acts; the card is
|
|
240
240
|
// repainted with its current link (or the honest absence of one).
|
|
241
241
|
store.consumeTelegramProposalActions(proposal.id, now);
|
|
242
|
-
const wanted =
|
|
242
|
+
const wanted = phoneProposalLink(store, proposal, actionRepos, "telegram");
|
|
243
243
|
const link = phoneLinkButton(origin, wanted);
|
|
244
244
|
ack(link === null ? "this step finishes on the computer" : "open the button below to finish this step");
|
|
245
245
|
edit(handoffCardText(preview.text, linkNote(origin, wanted)), keyboardWith(null, link));
|
|
@@ -545,7 +545,7 @@ async function runTelegramConversation(row, args) {
|
|
|
545
545
|
// or went away carries the current truth, never a stored URL.
|
|
546
546
|
const proposal = part.kind === "card" && part.proposal !== null ? store.getLeadProposal(part.proposal) : null;
|
|
547
547
|
const origin = proposal === null ? null : options.phoneOrigin?.() ?? null;
|
|
548
|
-
const wanted = proposal === null ? null :
|
|
548
|
+
const wanted = proposal === null ? null : phoneProposalLink(store, proposal, repos);
|
|
549
549
|
const keyboard = keyboardWith(part.keyboard, phoneLinkButton(origin, wanted));
|
|
550
550
|
// The lead's own words carry their bold anchors and labelled links as entities, never as Markdown characters.
|
|
551
551
|
const voiced = part.kind === "reply" ? telegramReply(part.text) : null;
|
|
@@ -625,7 +625,7 @@ async function runTelegramConversation(row, args) {
|
|
|
625
625
|
for (const image of selected)
|
|
626
626
|
parts.push({ kind: "image", text: image.caption, taskId: image.taskId, run: image.run, artifact: image.artifact, sha256: image.sha256 });
|
|
627
627
|
for (const proposal of proposals) {
|
|
628
|
-
const preview =
|
|
628
|
+
const preview = phoneProposalPreview(store, proposal, repos);
|
|
629
629
|
const keyboard = preview.buttons ? mintCardTokens(store, binding, proposal.id, now).keyboard : null;
|
|
630
630
|
parts.push({ kind: "card", text: preview.text, proposal: proposal.id, keyboard });
|
|
631
631
|
}
|
|
@@ -763,11 +763,13 @@ async function runTelegramConversation(row, args) {
|
|
|
763
763
|
react: () => transport("setMessageReaction", { chat_id: chatId, message_id: Number(row.messageId), reaction: [{ type: "emoji", emoji: WARM_EMOJI }] }),
|
|
764
764
|
typing: () => transport("sendChatAction", { chat_id: chatId, action: "typing" }),
|
|
765
765
|
});
|
|
766
|
+
const replyImage = row.replyTo === null ? undefined : store.telegramMessageBindings(binding, row.replyTo).find(one => one.taskId === row.taskId && one.run === row.sourceRun && one.image !== undefined)?.image;
|
|
766
767
|
let outcome;
|
|
767
768
|
try {
|
|
768
769
|
outcome = await runLeadTurn({
|
|
769
770
|
store, who, session, thread, config, key: null, message: row.text, requestId: row.request,
|
|
770
771
|
...(row.context === null ? {} : { context: row.context }),
|
|
772
|
+
...(replyImage === undefined ? {} : { replyImage }),
|
|
771
773
|
...(options.subscriptionRunner === undefined ? {} : { subscriptionRunner: options.subscriptionRunner }),
|
|
772
774
|
clock, evidenceRoot: options.evidenceRoot, revalidate, mediaDelivery: "documents", channel: "telegram", onProgress: warm.onProgress,
|
|
773
775
|
});
|
package/dist/telegram.js
CHANGED
|
@@ -1852,7 +1852,7 @@ function applyConversation(context, update, effects) {
|
|
|
1852
1852
|
if (tasks.length === 1) {
|
|
1853
1853
|
taskId = tasks[0];
|
|
1854
1854
|
sourceRun = bindings.find(one => one.run !== null)?.run ?? null;
|
|
1855
|
-
context_ = replyContextFor(taskId, sourceRun);
|
|
1855
|
+
context_ = replyContextFor(taskId, sourceRun, bindings.find(one => one.image !== undefined)?.image);
|
|
1856
1856
|
}
|
|
1857
1857
|
}
|
|
1858
1858
|
// No reply target: the task this chat chose to talk about, if any. The
|
package/dist/tidy.d.ts
ADDED
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { type Store } from "./store.js";
|
|
2
|
+
import type { WorkSummaryAccess } from "./work-summary.js";
|
|
3
|
+
export type TidyRule = "release" | "routine" | "ci" | "finished";
|
|
4
|
+
/** The preview's groups, in order. "finished" is a person's own choice only; tidy never applies it on its own. */
|
|
5
|
+
export declare const TIDY_GROUPS: readonly {
|
|
6
|
+
rule: TidyRule;
|
|
7
|
+
label: string;
|
|
8
|
+
}[];
|
|
9
|
+
export declare const TIDY_DEFAULT_DAYS = 14;
|
|
10
|
+
/** At most this many tasks are put away automatically per pass. */
|
|
11
|
+
export declare const TIDY_PASS_LIMIT = 25;
|
|
12
|
+
/** One task tidy would put away: its family's current task, every version that goes with it (`members`, task_ref ids),
|
|
13
|
+
* why, and under which rule. */
|
|
14
|
+
export type TidyItem = {
|
|
15
|
+
rule: TidyRule;
|
|
16
|
+
taskId: string;
|
|
17
|
+
title: string;
|
|
18
|
+
repo: string | null;
|
|
19
|
+
reason: string;
|
|
20
|
+
updatedAt: string;
|
|
21
|
+
members: number[];
|
|
22
|
+
};
|
|
23
|
+
/** What the release journals say about one release task (release.ts writes them; read only). */
|
|
24
|
+
export type ReleaseFact = {
|
|
25
|
+
taskId: string;
|
|
26
|
+
version: string;
|
|
27
|
+
product: string;
|
|
28
|
+
candidate: string;
|
|
29
|
+
superseded: boolean;
|
|
30
|
+
done: boolean;
|
|
31
|
+
published: boolean;
|
|
32
|
+
stopped: boolean;
|
|
33
|
+
};
|
|
34
|
+
/** Every release journal's facts, or why they can't be trusted: one unreadable journal leaves the release rule out. */
|
|
35
|
+
export type ReleaseFacts = {
|
|
36
|
+
facts: ReleaseFact[];
|
|
37
|
+
problem: string | null;
|
|
38
|
+
};
|
|
39
|
+
/** Reads `releases/*.json` under the plane's state folder (the database's folder), written only by `toolroll release`.
|
|
40
|
+
* A symlink, a non-file, an oversized or unreadable journal makes the whole answer untrusted (`problem`), so the
|
|
41
|
+
* release rule then puts nothing away: a journal it can't read might be the one that says a release is in flight. */
|
|
42
|
+
export declare function readReleaseFacts(stateDir: string): ReleaseFacts;
|
|
43
|
+
/** The release journals beside this database (its folder is the plane's state folder). An in-memory or relative
|
|
44
|
+
* database has no state folder, so the release rule stays off rather than reading whatever folder it runs in. */
|
|
45
|
+
export declare function releaseFactsFor(databaseFile: string): ReleaseFacts;
|
|
46
|
+
/** -1, 0 or 1: numeric parts first, then a release above any of its pre-releases. */
|
|
47
|
+
export declare function compareVersions(a: string, b: string): number;
|
|
48
|
+
/** The failing runs older "Checks failed" cards of this trigger name (their own GitHub run links) that aren't on record
|
|
49
|
+
* yet, newest first, at most `limit`: the checks trigger reads each from GitHub so tidy can tell where it ran. */
|
|
50
|
+
export declare function unprovenNoticeRuns(store: Store, trigger: number, repo: string, limit?: number): number[];
|
|
51
|
+
/** A completed workflow run on the watched branch, as the checks trigger read it from GitHub (its poll through the
|
|
52
|
+
* person's own gh login, or its signed webhook): kept once per run. Only a push to the watched branch of the watched
|
|
53
|
+
* repository counts (a pull request from a fork whose branch is also called main does not). */
|
|
54
|
+
export declare function recordBranchCheckRun(store: Store, watched: {
|
|
55
|
+
repo: string;
|
|
56
|
+
branch: string;
|
|
57
|
+
}, run: {
|
|
58
|
+
id?: number | undefined;
|
|
59
|
+
name?: string | undefined;
|
|
60
|
+
head_sha?: string | undefined;
|
|
61
|
+
head_branch?: string | undefined;
|
|
62
|
+
conclusion?: string | undefined;
|
|
63
|
+
created_at?: string | undefined;
|
|
64
|
+
event?: string | undefined;
|
|
65
|
+
head_repository?: {
|
|
66
|
+
full_name?: string | undefined;
|
|
67
|
+
} | undefined;
|
|
68
|
+
}, now: Date): boolean;
|
|
69
|
+
/** What tidy would put away now, in group order, oldest first within a group. `days`: also offer finished tasks
|
|
70
|
+
* untouched that long (a person's preview only); null is tidy's own automatic rules. `access`: whose lists. */
|
|
71
|
+
export declare function tidyPreview(store: Store, now: Date, input: {
|
|
72
|
+
releases: ReleaseFacts;
|
|
73
|
+
days: number | null;
|
|
74
|
+
access?: WorkSummaryAccess;
|
|
75
|
+
}): TidyItem[];
|
|
76
|
+
/** The preview's identity: exactly which tasks under which rules, for how many days. A person's confirmation names it. */
|
|
77
|
+
export declare function tidyDigest(items: readonly TidyItem[], days: number | null): string;
|
|
78
|
+
/** The preview in its groups (empty ones left out), with each group's label. */
|
|
79
|
+
export declare function tidyGroups(items: readonly TidyItem[], days: number): {
|
|
80
|
+
rule: TidyRule;
|
|
81
|
+
label: string;
|
|
82
|
+
items: TidyItem[];
|
|
83
|
+
}[];
|
|
84
|
+
/** A day count from a person (1–365), or the default. */
|
|
85
|
+
export declare function tidyDays(raw: string | null | undefined): number | null;
|
|
86
|
+
export type TidyApply = {
|
|
87
|
+
ok: true;
|
|
88
|
+
archived: TidyItem[];
|
|
89
|
+
skipped: {
|
|
90
|
+
taskId: string;
|
|
91
|
+
message: string;
|
|
92
|
+
}[];
|
|
93
|
+
} | {
|
|
94
|
+
ok: false;
|
|
95
|
+
reason: "changed" | "outside" | "empty";
|
|
96
|
+
message: string;
|
|
97
|
+
items: TidyItem[];
|
|
98
|
+
digest: string;
|
|
99
|
+
};
|
|
100
|
+
/** A person puts away exactly what they previewed (or the ticked part of it), in one write transaction that recomputes
|
|
101
|
+
* the preview and refuses when its digest moved or a ticked task isn't in it. */
|
|
102
|
+
export declare function applyTidy(store: Store, now: Date, input: {
|
|
103
|
+
by: string;
|
|
104
|
+
days: number;
|
|
105
|
+
digest: string;
|
|
106
|
+
only: readonly string[] | null;
|
|
107
|
+
releases: ReleaseFacts;
|
|
108
|
+
access?: WorkSummaryAccess;
|
|
109
|
+
}): TidyApply;
|
|
110
|
+
/** Tidy on its own (the worker's reconcile pass): its automatic rules only, at most `limit` tasks, in one write
|
|
111
|
+
* transaction. Idempotent: what is put away is skipped next time, and a restored task is never put away again. */
|
|
112
|
+
export declare function runTidy(store: Store, now: Date, releases: ReleaseFacts, limit?: number, access?: WorkSummaryAccess): TidyItem[];
|
|
113
|
+
/** Whether this person may still put away or restore work in this project, read under the write lock (check and write
|
|
114
|
+
* together): an active approver who can see it. Null when they may; otherwise why not. */
|
|
115
|
+
export declare function approverStandsNow(store: Store, name: string, repo: string | null): string | null;
|
|
116
|
+
/** The repository of a task's family, from its first version (all versions share it). */
|
|
117
|
+
export declare function familyRepoOf(store: Store, refs: readonly number[]): string | null;
|
|
118
|
+
/** "Archived by tidy: <reason>" or "Archived by <person>: <reason>": the one sentence every surface shows. */
|
|
119
|
+
export declare function archivedWords(archived: {
|
|
120
|
+
by: string;
|
|
121
|
+
byKind: "person" | "tidy";
|
|
122
|
+
reason: string;
|
|
123
|
+
}): string;
|
|
124
|
+
/** The release journals beside the store's own database file (none for an in-memory one). */
|
|
125
|
+
export declare function releaseFactsOf(store: Store): ReleaseFacts;
|
|
126
|
+
/** The lists one person sees, for tidy: every project for an unrestricted account, otherwise exactly theirs. The CLI's
|
|
127
|
+
* preview (`--as <name>`) and its apply read the same scope, so the same records give the same digest. */
|
|
128
|
+
export declare function accessOf(store: Store, name: string): WorkSummaryAccess;
|
|
129
|
+
/** Narrows `access` to the caller's own lens (a remote person's project limit): never wider. No lens: unchanged. */
|
|
130
|
+
export declare function withinLens(access: WorkSummaryAccess, lens: readonly string[] | null): WorkSummaryAccess;
|