toolroll 0.9.54 → 0.9.56
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 +19 -0
- package/README.md +29 -12
- package/dist/action-ledger.d.ts +2 -4
- package/dist/action-ledger.js +2 -10
- package/dist/agent-onboard.js +4 -1
- package/dist/approval-policy.d.ts +5 -5
- package/dist/approval-policy.js +4 -4
- package/dist/approval-rules-ui.d.ts +3 -2
- package/dist/approval-rules-ui.js +17 -22
- package/dist/assignment-ui.d.ts +3 -2
- package/dist/assignment-ui.js +4 -11
- package/dist/backup-ui.d.ts +2 -1
- package/dist/backup-ui.js +16 -27
- package/dist/brand-mark.d.ts +3 -2
- package/dist/brand-mark.js +4 -4
- package/dist/browser/workspace.css +1 -1
- package/dist/browser/workspace.js +25 -25
- package/dist/browser-shell.d.ts +2 -1
- package/dist/browser-shell.js +9 -9
- package/dist/browser-workspace.d.ts +14 -15
- package/dist/browser-workspace.js +0 -3
- package/dist/budget-alerts.js +3 -3
- package/dist/chat-actions.d.ts +23 -18
- package/dist/chat-actions.js +110 -88
- package/dist/chat-ask.d.ts +2 -2
- package/dist/chat-ask.js +5 -5
- package/dist/chat-channel.d.ts +15 -15
- package/dist/chat-channel.js +20 -20
- package/dist/chat-controls.d.ts +0 -4
- package/dist/chat-controls.js +0 -1
- package/dist/chat-core.js +1 -1
- package/dist/chat-delivery-state.js +2 -2
- package/dist/chat-delivery.d.ts +2 -2
- package/dist/chat-delivery.js +27 -34
- package/dist/chat-flow.js +3 -3
- package/dist/chat-messages.d.ts +1 -1
- package/dist/chat-messages.js +4 -4
- package/dist/chat-migration.d.ts +1 -1
- package/dist/chat-migration.js +11 -11
- package/dist/chat-polish.d.ts +5 -4
- package/dist/chat-polish.js +9 -10
- package/dist/chat-rooms.js +3 -3
- package/dist/chat-warmth.d.ts +2 -2
- package/dist/check-levels-ui.d.ts +2 -1
- package/dist/check-levels-ui.js +26 -53
- package/dist/cli.d.ts +3 -1
- package/dist/cli.js +15 -10
- package/dist/coding-shipping-ui.d.ts +2 -1
- package/dist/coding-shipping-ui.js +6 -6
- package/dist/coding-ui.d.ts +3 -1
- package/dist/coding-ui.js +30 -29
- package/dist/contracts/chat-actions.d.ts +32 -27
- package/dist/contracts/chat-actions.js +29 -11
- package/dist/contracts/chat-content.d.ts +1 -1
- package/dist/contracts/chat-content.js +1 -1
- package/dist/contracts/chat-tables.js +4 -4
- package/dist/contracts/cli.d.ts +1 -3
- package/dist/contracts/console-api.d.ts +7 -7
- package/dist/contracts/console-api.js +13 -12
- package/dist/contracts/flow-propose.d.ts +3 -3
- package/dist/contracts/flow.d.ts +132 -125
- package/dist/contracts/flow.js +27 -12
- package/dist/contracts/health.d.ts +1 -3
- package/dist/contracts/lead-context.d.ts +1 -1
- package/dist/contracts/lead-context.js +2 -2
- package/dist/contracts/lead-tools.d.ts +20 -18
- package/dist/contracts/lead-tools.js +15 -15
- package/dist/contracts/stage-output.d.ts +1 -1
- package/dist/contracts/stage-output.js +1 -1
- package/dist/contracts/store-json.d.ts +23 -22
- package/dist/contracts/store-json.js +17 -17
- package/dist/contracts/{teammate-turn.d.ts → subagent-turn.d.ts} +5 -5
- package/dist/contracts/{teammate-turn.js → subagent-turn.js} +7 -7
- package/dist/control-ui.d.ts +5 -4
- package/dist/control-ui.js +9 -34
- package/dist/converse.d.ts +23 -23
- package/dist/converse.js +28 -28
- package/dist/coordinator-proposals.d.ts +2 -2
- package/dist/coordinator-proposals.js +1 -1
- package/dist/coordinator.js +1 -1
- package/dist/credentials-ui.d.ts +5 -4
- package/dist/credentials-ui.js +23 -24
- package/dist/demo-chat.d.ts +3 -3
- package/dist/demo-chat.js +29 -76
- package/dist/deprecations.d.ts +12 -0
- package/dist/deprecations.js +20 -0
- package/dist/desktop-update-gate.js +8 -4
- package/dist/desktop-update.js +6 -1
- package/dist/discord-chat.js +6 -6
- package/dist/discord-settings.d.ts +3 -2
- package/dist/discord-settings.js +17 -42
- package/dist/dispatch.d.ts +1 -1
- package/dist/dispatch.js +1 -1
- package/dist/envelope.js +10 -1
- package/dist/evidence-pack.d.ts +2 -1
- package/dist/evidence-pack.js +45 -49
- package/dist/export-ui.d.ts +7 -2
- package/dist/export-ui.js +4 -10
- package/dist/export.js +7 -7
- package/dist/flow-engine.d.ts +2 -2
- package/dist/flow-engine.js +21 -21
- package/dist/flow-gallery-ui.d.ts +4 -3
- package/dist/flow-gallery-ui.js +28 -43
- package/dist/flow-insights.d.ts +1 -1
- package/dist/flow-share.js +13 -8
- package/dist/flow-starters-ui.d.ts +2 -1
- package/dist/flow-starters-ui.js +12 -15
- package/dist/flow-steps.d.ts +5 -5
- package/dist/flow-steps.js +19 -19
- package/dist/flow-triggers.d.ts +2 -1
- package/dist/flow-triggers.js +17 -15
- package/dist/flows-cli.js +1 -1
- package/dist/flows-ui.d.ts +4 -3
- package/dist/flows-ui.js +38 -49
- package/dist/flows.js +21 -20
- package/dist/guides.js +112 -6
- package/dist/html.d.ts +76 -0
- package/dist/html.js +173 -0
- package/dist/integrations-ui.d.ts +2 -1
- package/dist/integrations-ui.js +19 -23
- package/dist/invoke.js +1 -1
- package/dist/kits-ui.d.ts +5 -4
- package/dist/kits-ui.js +22 -24
- package/dist/kits.d.ts +12 -12
- package/dist/kits.js +31 -31
- package/dist/knowledge-ui.d.ts +6 -5
- package/dist/knowledge-ui.js +26 -25
- package/dist/{mate-cli.d.ts → lead-cli.d.ts} +11 -11
- package/dist/{mate-cli.js → lead-cli.js} +38 -38
- package/dist/lead-commitments.js +4 -4
- package/dist/lead-context.d.ts +12 -2
- package/dist/lead-context.js +15 -17
- package/dist/{mate-contract.d.ts → lead-contract.d.ts} +3 -3
- package/dist/{mate-contract.js → lead-contract.js} +7 -6
- package/dist/{mate-doors.d.ts → lead-doors.d.ts} +6 -6
- package/dist/{mate-doors.js → lead-doors.js} +24 -24
- package/dist/lead-follow.d.ts +5 -5
- package/dist/lead-follow.js +9 -9
- package/dist/lead-people.d.ts +5 -5
- package/dist/lead-people.js +14 -14
- package/dist/{mate-progress.d.ts → lead-progress.d.ts} +9 -9
- package/dist/{mate-progress.js → lead-progress.js} +3 -3
- package/dist/{mate-tools.d.ts → lead-tools.d.ts} +19 -19
- package/dist/{mate-tools.js → lead-tools.js} +109 -101
- package/dist/{mate.d.ts → lead.d.ts} +27 -27
- package/dist/{mate.js → lead.js} +102 -102
- package/dist/ledger-view.d.ts +2 -1
- package/dist/ledger-view.js +27 -29
- package/dist/limits-ui.d.ts +3 -2
- package/dist/limits-ui.js +8 -8
- package/dist/live-bus.d.ts +50 -8
- package/dist/live-bus.js +133 -50
- package/dist/mcp-connect.d.ts +1 -1
- package/dist/mcp-connect.js +3 -3
- package/dist/mcp-core.js +1 -1
- package/dist/mcp-oauth.js +35 -36
- package/dist/memory-pass.d.ts +2 -2
- package/dist/memory-pass.js +7 -7
- package/dist/models-ui.d.ts +2 -1
- package/dist/models-ui.js +25 -35
- package/dist/monitoring-ui.d.ts +4 -3
- package/dist/monitoring-ui.js +13 -26
- package/dist/notification-rows.d.ts +2 -2
- package/dist/openrouter-models.d.ts +2 -1
- package/dist/openrouter-models.js +5 -9
- package/dist/operate.d.ts +3 -3
- package/dist/operate.js +46 -41
- package/dist/people-audit-ui.d.ts +2 -1
- package/dist/people-audit-ui.js +13 -13
- package/dist/policy-ui.d.ts +3 -2
- package/dist/policy-ui.js +17 -23
- package/dist/policy.d.ts +1 -1
- package/dist/principal.d.ts +1 -1
- package/dist/principal.js +2 -2
- package/dist/project-delete-ui.d.ts +4 -3
- package/dist/project-delete-ui.js +16 -28
- package/dist/project-delete.d.ts +1 -1
- package/dist/project-delete.js +26 -26
- package/dist/project-memory.js +1 -1
- package/dist/project-tools.d.ts +1 -1
- package/dist/project-tools.js +1 -1
- package/dist/pull-request-ui.d.ts +2 -1
- package/dist/pull-request-ui.js +17 -32
- package/dist/recipe-ui.d.ts +8 -7
- package/dist/recipe-ui.js +39 -32
- package/dist/release-adapters.d.ts +60 -0
- package/dist/release-adapters.js +435 -0
- package/dist/release-cli.d.ts +24 -0
- package/dist/release-cli.js +181 -0
- package/dist/release-gate.d.ts +80 -0
- package/dist/release-gate.js +150 -0
- package/dist/release-links.d.ts +29 -0
- package/dist/release-links.js +102 -0
- package/dist/release.d.ts +331 -0
- package/dist/release.js +550 -0
- package/dist/reply-shape.d.ts +2 -1
- package/dist/reply-shape.js +5 -5
- package/dist/repository-context-ui.d.ts +2 -1
- package/dist/repository-context-ui.js +2 -7
- package/dist/request-budget-ui.d.ts +2 -1
- package/dist/request-budget-ui.js +16 -16
- package/dist/result-review.d.ts +2 -3
- package/dist/result-review.js +3 -9
- package/dist/retention-ui.d.ts +7 -1
- package/dist/retention-ui.js +7 -11
- package/dist/retention.js +4 -4
- package/dist/scope.d.ts +2 -2
- package/dist/scout-report.d.ts +1 -1
- package/dist/scout-report.js +1 -1
- package/dist/serve.d.ts +11 -2
- package/dist/serve.js +105 -99
- package/dist/server/chat.d.ts +7 -10
- package/dist/server/chat.js +984 -1021
- package/dist/server/chrome.d.ts +291 -0
- package/dist/server/chrome.js +747 -0
- package/dist/server/console.css +2819 -0
- package/dist/server/flows.d.ts +2 -6
- package/dist/server/flows.js +854 -773
- package/dist/server/guards.d.ts +1 -1
- package/dist/server/guards.js +8 -5
- package/dist/server/handler-context.d.ts +1 -1
- package/dist/server/handler-context.js +1 -1
- package/dist/server/handler-registry.d.ts +8 -6
- package/dist/server/handler-registry.js +14 -2
- package/dist/server/http.d.ts +274 -0
- package/dist/server/http.js +239 -0
- package/dist/server/live.d.ts +34 -0
- package/dist/server/live.js +309 -0
- package/dist/server/pages.d.ts +2 -6
- package/dist/server/pages.js +808 -789
- package/dist/server/people-tokens.d.ts +1 -6
- package/dist/server/people-tokens.js +581 -573
- package/dist/server/remote.d.ts +4 -7
- package/dist/server/remote.js +39 -70
- package/dist/server/render-chat.d.ts +402 -0
- package/dist/server/render-chat.js +927 -0
- package/dist/server/render-pages.d.ts +535 -0
- package/dist/server/render-pages.js +1277 -0
- package/dist/server/render-people.d.ts +32 -0
- package/dist/server/render-people.js +121 -0
- package/dist/server/render-results.d.ts +744 -0
- package/dist/server/render-results.js +2237 -0
- package/dist/server/render-settings.d.ts +154 -0
- package/dist/server/render-settings.js +580 -0
- package/dist/server/render-tasks.d.ts +632 -0
- package/dist/server/render-tasks.js +2345 -0
- package/dist/server/request-context.d.ts +46 -0
- package/dist/server/request-context.js +17 -0
- package/dist/server/route-table.d.ts +25 -3
- package/dist/server/route-table.js +167 -77
- package/dist/server/runtime.d.ts +28 -20
- package/dist/server/runtime.js +7 -1
- package/dist/server/session.d.ts +138 -0
- package/dist/server/session.js +94 -0
- package/dist/server/settings.d.ts +1 -5
- package/dist/server/settings.js +2186 -2121
- package/dist/server/task-views.d.ts +11 -4
- package/dist/server/task-views.js +26 -22
- package/dist/server/tasks.d.ts +9 -9
- package/dist/server/tasks.js +1489 -1420
- package/dist/server-telemetry.d.ts +4 -3
- package/dist/server-telemetry.js +4 -8
- package/dist/setup-guide.d.ts +2 -2
- package/dist/skills-ui.d.ts +4 -3
- package/dist/skills-ui.js +14 -17
- package/dist/skills.d.ts +1 -1
- package/dist/skills.js +2 -1
- package/dist/slack-chat.d.ts +2 -2
- package/dist/slack-chat.js +6 -6
- package/dist/slack-settings.d.ts +3 -2
- package/dist/slack-settings.js +17 -42
- package/dist/spend-ui.d.ts +5 -4
- package/dist/spend-ui.js +17 -40
- package/dist/spend.d.ts +14 -14
- package/dist/spend.js +31 -31
- package/dist/sso-ui.d.ts +3 -2
- package/dist/sso-ui.js +26 -27
- package/dist/storage-ui.d.ts +2 -1
- package/dist/storage-ui.js +14 -33
- package/dist/store-baseline.d.ts +19 -0
- package/dist/store-baseline.js +2873 -0
- package/dist/store.d.ts +197 -249
- package/dist/store.js +747 -3084
- package/dist/subagent-admin.d.ts +53 -0
- package/dist/{teammate-admin.js → subagent-admin.js} +37 -37
- package/dist/{teammate-desk.d.ts → subagent-desk.d.ts} +22 -23
- package/dist/{teammate-desk.js → subagent-desk.js} +26 -35
- package/dist/{teammate-memory.d.ts → subagent-memory.d.ts} +17 -17
- package/dist/{teammate-memory.js → subagent-memory.js} +41 -41
- package/dist/{teammate-question.d.ts → subagent-question.d.ts} +6 -6
- package/dist/{teammate-question.js → subagent-question.js} +17 -17
- package/dist/{teammate-tools.d.ts → subagent-tools.d.ts} +18 -18
- package/dist/{teammate-tools.js → subagent-tools.js} +36 -36
- package/dist/{teammate-week.d.ts → subagent-week.d.ts} +10 -10
- package/dist/{teammate-week.js → subagent-week.js} +23 -23
- package/dist/{teammate-work.d.ts → subagent-work.d.ts} +21 -21
- package/dist/{teammate-work.js → subagent-work.js} +50 -50
- package/dist/subagents-ui.d.ts +22 -0
- package/dist/subagents-ui.js +137 -0
- package/dist/{teammates.d.ts → subagents.d.ts} +11 -11
- package/dist/{teammates.js → subagents.js} +21 -21
- package/dist/subscription-chat.d.ts +13 -13
- package/dist/subscription-chat.js +19 -19
- package/dist/surface.d.ts +19 -2
- package/dist/surface.js +20 -33
- package/dist/task-composer.d.ts +2 -1
- package/dist/task-composer.js +7 -7
- package/dist/task-status.d.ts +4 -3
- package/dist/task-status.js +15 -16
- package/dist/team-cli.d.ts +1 -0
- package/dist/team-cli.js +14 -2
- package/dist/team-http.d.ts +5 -9
- package/dist/team-http.js +5 -63
- package/dist/team-leads.js +13 -13
- package/dist/team-runtime.d.ts +2 -2
- package/dist/team-runtime.js +8 -8
- package/dist/team-ui.d.ts +2 -1
- package/dist/team-ui.js +2 -5
- package/dist/teams-chat.js +6 -6
- package/dist/teams-settings.d.ts +3 -2
- package/dist/teams-settings.js +20 -31
- package/dist/telegram-flow.d.ts +3 -3
- package/dist/telegram-flow.js +3 -3
- package/dist/{telegram-mate.d.ts → telegram-lead.d.ts} +5 -5
- package/dist/{telegram-mate.js → telegram-lead.js} +27 -27
- package/dist/telegram-settings.d.ts +3 -2
- package/dist/telegram-settings.js +14 -25
- package/dist/telegram-status.js +1 -1
- package/dist/telegram-team.d.ts +1 -1
- package/dist/telegram-team.js +5 -5
- package/dist/telegram.d.ts +1 -1
- package/dist/telegram.js +9 -30
- package/dist/text-limits.d.ts +18 -18
- package/dist/text-limits.js +18 -18
- package/dist/toolroll-update-ui.d.ts +3 -2
- package/dist/toolroll-update-ui.js +35 -39
- package/dist/toolroll-update.d.ts +8 -0
- package/dist/toolroll-update.js +45 -8
- package/dist/tools-ui.d.ts +5 -2
- package/dist/tools-ui.js +31 -31
- package/dist/when-html.d.ts +11 -3
- package/dist/when-html.js +5 -6
- package/dist/workspace-ui.d.ts +4 -2
- package/dist/workspace-ui.js +10 -10
- package/package.json +1 -2
- package/dist/server/shared.d.ts +0 -3151
- package/dist/server/shared.js +0 -12001
- package/dist/teammate-admin.d.ts +0 -53
- package/dist/teammates-ui.d.ts +0 -20
- package/dist/teammates-ui.js +0 -166
package/dist/demo-chat.js
CHANGED
|
@@ -4,48 +4,26 @@
|
|
|
4
4
|
* running build's progress live; without it the page still works by reload.
|
|
5
5
|
*/
|
|
6
6
|
import { START_COMMAND } from "./first-run.js";
|
|
7
|
+
import { html, postForm } from "./html.js";
|
|
7
8
|
import { headlineOf } from "./task-status.js";
|
|
8
9
|
const SUGGESTIONS = ["Fix the flaky refund test", "Rewrite the empty Payouts page", "Put the new invoice view behind a flag"];
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
function hint(csrf) {
|
|
12
|
-
return `<section class="demo-hint" aria-label="Get started">` +
|
|
13
|
-
`<p class="demo-hint-title">Ask for something, like “fix the flaky refund test”</p>` +
|
|
14
|
-
`<form method="post" action="/chat/demo/ask" class="demo-suggestions">${hidden(csrf)}` +
|
|
15
|
-
SUGGESTIONS.map(one => `<button type="submit" name="message" value="${esc(one)}">${esc(one)}</button>`).join("") +
|
|
16
|
-
`</form></section>`;
|
|
10
|
+
function hint() {
|
|
11
|
+
return html `<section class="demo-hint" aria-label="Get started"><p class="demo-hint-title">Ask for something, like “fix the flaky refund test”</p>${postForm("/chat/demo/ask", SUGGESTIONS.map(one => html `<button type="submit" name="message" value="${one}">${one}</button>`), { attrs: { class: "demo-suggestions" } })}</section>`;
|
|
17
12
|
}
|
|
18
|
-
function planCard(exchange
|
|
13
|
+
function planCard(exchange) {
|
|
19
14
|
const plan = exchange.plan;
|
|
20
15
|
const goal = exchange.note === null ? plan.goal : `${plan.goal} Also: ${exchange.note}`;
|
|
21
16
|
const actions = exchange.state === "proposed"
|
|
22
|
-
? `<div class="demo-actions">`
|
|
23
|
-
`<form method="post" action="/chat/demo/${exchange.id}/approve" class="approve-form">${hidden(csrf)}<button type="submit">Approve</button></form>` +
|
|
24
|
-
`<details class="demo-more"><summary>Change it</summary>` +
|
|
25
|
-
`<form method="post" action="/chat/demo/${exchange.id}/change">${hidden(csrf)}` +
|
|
26
|
-
`<label for="demo-change-${exchange.id}">What should change?</label>` +
|
|
27
|
-
`<textarea id="demo-change-${exchange.id}" name="note" rows="2" maxlength="500" required></textarea>` +
|
|
28
|
-
`<button type="submit">Update plan</button></form></details></div>`
|
|
17
|
+
? html `<div class="demo-actions">${postForm(`/chat/demo/${exchange.id}/approve`, html `<button type="submit">Approve</button>`, { attrs: { class: "approve-form" } })}<details class="demo-more"><summary>Change it</summary>${postForm(`/chat/demo/${exchange.id}/change`, html `<label for="demo-change-${exchange.id}">What should change?</label><textarea id="demo-change-${exchange.id}" name="note" rows="2" maxlength="500" required></textarea><button type="submit">Update plan</button>`)}</details></div>`
|
|
29
18
|
: exchange.state === "replaced"
|
|
30
|
-
? `<p class="meta">Replaced by the updated plan below.</p>`
|
|
31
|
-
: `<p class="meta">Approved.</p>`;
|
|
32
|
-
return `<section class="card demo-plan" aria-label="Plan">`
|
|
33
|
-
`<p class="demo-kicker">Plan · ${esc(plan.project)}</p>` +
|
|
34
|
-
`<h2>${esc(plan.title)}</h2>` +
|
|
35
|
-
`<p>${esc(goal)}</p>` +
|
|
36
|
-
`<h3>Boundaries</h3><ul>${plan.boundaries.map(one => `<li>${esc(one)}</li>`).join("")}</ul>` +
|
|
37
|
-
`<h3>Checks</h3><ul>${plan.checks.map(one => `<li>${esc(one)}</li>`).join("")}</ul>` +
|
|
38
|
-
actions + `</section>`;
|
|
19
|
+
? html `<p class="meta">Replaced by the updated plan below.</p>`
|
|
20
|
+
: html `<p class="meta">Approved.</p>`;
|
|
21
|
+
return html `<section class="card demo-plan" aria-label="Plan"><p class="demo-kicker">Plan · ${plan.project}</p><h2>${plan.title}</h2><p>${goal}</p><h3>Boundaries</h3><ul>${plan.boundaries.map(one => html `<li>${one}</li>`)}</ul><h3>Checks</h3><ul>${plan.checks.map(one => html `<li>${one}</li>`)}</ul>${actions}</section>`;
|
|
39
22
|
}
|
|
40
23
|
function buildCard(exchange) {
|
|
41
24
|
const stages = [["planning", "Planning"], ["building", "Building"], ["checking", "Running checks"]];
|
|
42
25
|
const at = stages.findIndex(([key]) => key === exchange.stage);
|
|
43
|
-
return `<section class="card demo-build" id="demo-${exchange.id}-work" aria-label="Build" aria-busy="true">`
|
|
44
|
-
`<p class="demo-kicker">${esc(exchange.plan.project)}</p>` +
|
|
45
|
-
`<h2>${esc(stages[Math.max(0, at)][1])}…</h2>` +
|
|
46
|
-
`<ol class="demo-steps">${stages.map(([, label], index) => `<li class="${index < at ? "done" : index === at ? "now" : ""}"${index === at ? ` aria-current="step"` : ""}>${esc(label)}</li>`).join("")}</ol>` +
|
|
47
|
-
(exchange.progress === null ? "" : `<p class="meta demo-progress">${esc(exchange.progress)}</p>`) +
|
|
48
|
-
`</section>`;
|
|
26
|
+
return html `<section class="card demo-build" id="demo-${exchange.id}-work" aria-label="Build" aria-busy="true"><p class="demo-kicker">${exchange.plan.project}</p><h2>${stages[Math.max(0, at)][1]}…</h2><ol class="demo-steps">${stages.map(([, label], index) => html `<li class="${index < at ? "done" : index === at ? "now" : ""}"${index === at ? html ` aria-current="step"` : ""}>${label}</li>`)}</ol>${exchange.progress === null ? "" : html `<p class="meta demo-progress">${exchange.progress}</p>`}</section>`;
|
|
49
27
|
}
|
|
50
28
|
function diffHtml(diff) {
|
|
51
29
|
return diff.replace(/\n$/, "").split("\n").map(line => {
|
|
@@ -53,71 +31,46 @@ function diffHtml(diff) {
|
|
|
53
31
|
: line.startsWith("+++") || line.startsWith("---") ? "meta"
|
|
54
32
|
: line.startsWith("@@") ? "hunk"
|
|
55
33
|
: line.startsWith("+") ? "add" : line.startsWith("-") ? "del" : "ctx";
|
|
56
|
-
return `<span class="demo-diff-${kind}">${
|
|
57
|
-
})
|
|
34
|
+
return html `<span class="demo-diff-${kind}">${line || " "}</span>`;
|
|
35
|
+
});
|
|
58
36
|
}
|
|
59
|
-
function resultCard(exchange,
|
|
37
|
+
function resultCard(exchange, result) {
|
|
60
38
|
if (result === null)
|
|
61
|
-
return `<section class="card demo-result"><p class="meta">This result's saved evidence is unavailable.</p></section>`;
|
|
39
|
+
return html `<section class="card demo-result"><p class="meta">This result's saved evidence is unavailable.</p></section>`;
|
|
62
40
|
const passed = result.checks.status === "passed";
|
|
63
41
|
// The shared headline (task-status.ts): the same words as every real task.
|
|
64
42
|
const headline = headlineOf({ stage: exchange.state === "complete" ? "complete" : exchange.state === "sent-back" ? "building" : "finished",
|
|
65
43
|
checks: { status: passed ? "passed" : "failed", exitCode: null, head: null } });
|
|
66
|
-
const status = `<span class="badge${headline === "Complete" ? " demo-complete" : headline === "Ready for review" ? " demo-ready" : ""}" data-headline="${headline}">${headline}</span>`;
|
|
67
|
-
const summary = `${result.files} file${result.files === 1 ? "" : "s"} changed · +${result.additions} −${result.deletions} ·
|
|
68
|
-
`<span class="${passed ? "demo-pass" : "demo-fail"}">${esc(result.checks.detail)}</span>`;
|
|
44
|
+
const status = html `<span class="badge${headline === "Complete" ? " demo-complete" : headline === "Ready for review" ? " demo-ready" : ""}" data-headline="${headline}">${headline}</span>`;
|
|
45
|
+
const summary = html `${result.files} file${result.files === 1 ? "" : "s"} changed · +${result.additions} −${result.deletions} · <span class="${passed ? "demo-pass" : "demo-fail"}">${result.checks.detail}</span>`;
|
|
69
46
|
const actions = exchange.state === "ready"
|
|
70
|
-
? `<div class="demo-actions">`
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
`<form method="post" action="/chat/demo/${exchange.id}/revise">${hidden(csrf)}` +
|
|
74
|
-
`<label for="demo-revise-${exchange.id}">What should change?</label>` +
|
|
75
|
-
`<textarea id="demo-revise-${exchange.id}" name="note" rows="2" maxlength="500" required></textarea>` +
|
|
76
|
-
`<button type="submit">Send back</button></form></details></div>`
|
|
77
|
-
: `<p class="meta"><a href="${esc(result.taskHref)}">Open in Tasks</a></p>`;
|
|
78
|
-
return `<section class="card demo-result" id="demo-${exchange.id}-work" aria-label="Result">` +
|
|
79
|
-
`<p class="demo-state">${status}<span class="meta">${esc(exchange.plan.project)}</span></p>` +
|
|
80
|
-
`<h2>${esc(exchange.plan.title)}</h2>` +
|
|
81
|
-
`<p>${esc(exchange.plan.conclusion)}</p>` +
|
|
82
|
-
`<p class="meta">${summary}</p>` +
|
|
83
|
-
actions +
|
|
84
|
-
(result.diff === null ? "" : `<details class="demo-evidence"${exchange.state === "ready" ? " open" : ""}><summary>Changes</summary><pre class="demo-diff">${diffHtml(result.diff)}</pre></details>`) +
|
|
85
|
-
(result.checkLog === null ? "" : `<details class="demo-evidence"><summary>Check log</summary><pre class="demo-log">${esc(result.checkLog)}</pre></details>`) +
|
|
86
|
-
(result.screenshot === null ? "" : `<details class="demo-evidence"><summary>Screenshot</summary><figure><img src="${esc(result.screenshot.href)}" alt="${esc(result.screenshot.caption)}" width="960" height="600"><figcaption class="meta">${esc(result.screenshot.caption)}</figcaption></figure></details>`) +
|
|
87
|
-
`</section>`;
|
|
47
|
+
? html `<div class="demo-actions">${postForm(`/chat/demo/${exchange.id}/complete`, html `<button type="submit" class="demo-primary">Complete</button>`)}<details class="demo-more"><summary>Request changes</summary>${postForm(`/chat/demo/${exchange.id}/revise`, html `<label for="demo-revise-${exchange.id}">What should change?</label><textarea id="demo-revise-${exchange.id}" name="note" rows="2" maxlength="500" required></textarea><button type="submit">Send back</button>`)}</details></div>`
|
|
48
|
+
: html `<p class="meta"><a href="${result.taskHref}">Open in Tasks</a></p>`;
|
|
49
|
+
return html `<section class="card demo-result" id="demo-${exchange.id}-work" aria-label="Result"><p class="demo-state">${status}<span class="meta">${exchange.plan.project}</span></p><h2>${exchange.plan.title}</h2><p>${exchange.plan.conclusion}</p><p class="meta">${summary}</p>${actions}${result.diff === null ? "" : html `<details class="demo-evidence"${exchange.state === "ready" ? html ` open` : ""}><summary>Changes</summary><pre class="demo-diff">${diffHtml(result.diff)}</pre></details>`}${result.checkLog === null ? "" : html `<details class="demo-evidence"><summary>Check log</summary><pre class="demo-log">${result.checkLog}</pre></details>`}${result.screenshot === null ? "" : html `<details class="demo-evidence"><summary>Screenshot</summary><figure><img src="${result.screenshot.href}" alt="${result.screenshot.caption}" width="960" height="600"><figcaption class="meta">${result.screenshot.caption}</figcaption></figure></details>`}</section>`;
|
|
88
50
|
}
|
|
89
51
|
/** The conversation itself; the live script swaps this region in place. */
|
|
90
|
-
export function demoThreadHtml(exchanges,
|
|
52
|
+
export function demoThreadHtml(exchanges, resultOf) {
|
|
91
53
|
if (exchanges.length === 0)
|
|
92
|
-
return hint(
|
|
93
|
-
return exchanges.map(exchange => {
|
|
54
|
+
return hint();
|
|
55
|
+
return html `${exchanges.map(exchange => {
|
|
94
56
|
const parts = [
|
|
95
|
-
`<div class="demo-said demo-you"><p>${
|
|
96
|
-
`<div class="demo-said demo-lead"><p class="demo-who">Lead</p><p>${
|
|
97
|
-
planCard(exchange
|
|
57
|
+
html `<div class="demo-said demo-you"><p>${exchange.asked}</p></div>`,
|
|
58
|
+
html `<div class="demo-said demo-lead"><p class="demo-who">Lead</p><p>${exchange.reply}</p></div>`,
|
|
59
|
+
planCard(exchange),
|
|
98
60
|
];
|
|
99
61
|
if (exchange.state === "working")
|
|
100
62
|
parts.push(buildCard(exchange));
|
|
101
63
|
if (exchange.state === "ready" || exchange.state === "complete" || exchange.state === "sent-back")
|
|
102
|
-
parts.push(resultCard(exchange,
|
|
64
|
+
parts.push(resultCard(exchange, resultOf(exchange)));
|
|
103
65
|
if (exchange.state === "complete") {
|
|
104
|
-
parts.push(`<div class="demo-said demo-lead"><p class="demo-who">Lead</p><p>Done. That's the whole loop: ask, approve, Ready, Complete. Ask for something else whenever you like.</p></div>`, `<section class="card demo-handoff" data-demo-handoff aria-label="Your own project"><h2>Now try it on your own project</h2>`
|
|
105
|
-
`<p>In your repository's folder, run:</p><pre class="demo-command"><code>${esc(START_COMMAND)}</code></pre>` +
|
|
106
|
-
`<p class="meta">It opens in your browser, already signed in.</p></section>`);
|
|
66
|
+
parts.push(html `<div class="demo-said demo-lead"><p class="demo-who">Lead</p><p>Done. That's the whole loop: ask, approve, Ready, Complete. Ask for something else whenever you like.</p></div>`, html `<section class="card demo-handoff" data-demo-handoff aria-label="Your own project"><h2>Now try it on your own project</h2><p>In your repository's folder, run:</p><pre class="demo-command"><code>${START_COMMAND}</code></pre><p class="meta">It opens in your browser, already signed in.</p></section>`);
|
|
107
67
|
}
|
|
108
|
-
return `<article class="demo-turn" id="demo-${exchange.id}">${parts
|
|
109
|
-
})
|
|
68
|
+
return html `<article class="demo-turn" id="demo-${exchange.id}">${parts}</article>`;
|
|
69
|
+
})}`;
|
|
110
70
|
}
|
|
111
71
|
export function demoChatHtml(input) {
|
|
112
72
|
const working = input.exchanges.some(one => one.state === "working");
|
|
113
|
-
return `<div class="demo-chat">`
|
|
114
|
-
(input.problem === null ? "" : `<p class="problem" role="alert">${esc(input.problem)}</p>`) +
|
|
115
|
-
`<div id="demo-thread" class="demo-thread" aria-live="polite" data-version="${input.version}" data-working="${working ? "1" : "0"}">` +
|
|
116
|
-
demoThreadHtml(input.exchanges, input.csrf, input.resultOf) + `</div>` +
|
|
117
|
-
`<form method="post" action="/chat/demo/ask" class="demo-composer">${hidden(input.csrf)}` +
|
|
118
|
-
`<label for="demo-message" class="so-sr-only">Message the lead</label>` +
|
|
119
|
-
`<textarea id="demo-message" name="message" rows="2" maxlength="500" placeholder="Ask the lead for a change" required></textarea>` +
|
|
120
|
-
`<button type="submit" class="demo-primary">Send</button></form></div>`;
|
|
73
|
+
return html `<div class="demo-chat">${input.problem === null ? "" : html `<p class="problem" role="alert">${input.problem}</p>`}<div id="demo-thread" class="demo-thread" aria-live="polite" data-version="${input.version}" data-working="${working ? "1" : "0"}">${demoThreadHtml(input.exchanges, input.resultOf)}</div>${postForm("/chat/demo/ask", html `<label for="demo-message" class="so-sr-only">Message the lead</label><textarea id="demo-message" name="message" rows="2" maxlength="500" placeholder="Ask the lead for a change" required></textarea><button type="submit" class="demo-primary">Send</button>`, { attrs: { class: "demo-composer" } })}</div>`;
|
|
121
74
|
}
|
|
122
75
|
/**
|
|
123
76
|
* Keeps a running build live: polls while one is working and swaps the
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* D5 (schema v117): one AI concept, the lead. The central team service (`connect`, the central `lead list|create|update|
|
|
3
|
+
* member|transfer`, `conversation …`, and `chat`/`brief` with --lead, --conversation or a saved profile) and native
|
|
4
|
+
* coding sessions (`session …`) are deprecated. For this release they still work exactly as before, but they are
|
|
5
|
+
* hidden from help, the command contract and the console, and each run says so once on stderr — never on stdout, so a
|
|
6
|
+
* `--json` answer stays one envelope. Their code goes in the next minor release.
|
|
7
|
+
*/
|
|
8
|
+
export type Deprecated = "team" | "session";
|
|
9
|
+
/** The one line a deprecated command prints on stderr: what it is, when it goes, and what to use instead. */
|
|
10
|
+
export declare function deprecationWarning(command: string, kind: Deprecated): string;
|
|
11
|
+
/** What a deprecated console page or API says about itself. */
|
|
12
|
+
export declare const DEPRECATED_PAGE: Record<Deprecated, string>;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* D5 (schema v117): one AI concept, the lead. The central team service (`connect`, the central `lead list|create|update|
|
|
3
|
+
* member|transfer`, `conversation …`, and `chat`/`brief` with --lead, --conversation or a saved profile) and native
|
|
4
|
+
* coding sessions (`session …`) are deprecated. For this release they still work exactly as before, but they are
|
|
5
|
+
* hidden from help, the command contract and the console, and each run says so once on stderr — never on stdout, so a
|
|
6
|
+
* `--json` answer stays one envelope. Their code goes in the next minor release.
|
|
7
|
+
*/
|
|
8
|
+
const NEXT_STEP = {
|
|
9
|
+
team: "Talk to your lead with `toolroll chat`.",
|
|
10
|
+
session: "Queue work with `toolroll task add`.",
|
|
11
|
+
};
|
|
12
|
+
/** The one line a deprecated command prints on stderr: what it is, when it goes, and what to use instead. */
|
|
13
|
+
export function deprecationWarning(command, kind) {
|
|
14
|
+
return `Warning: \`toolroll ${command}\` is deprecated and will be removed in the next minor release. ${NEXT_STEP[kind]}`;
|
|
15
|
+
}
|
|
16
|
+
/** What a deprecated console page or API says about itself. */
|
|
17
|
+
export const DEPRECATED_PAGE = {
|
|
18
|
+
team: "Team chat is deprecated and will be removed in the next minor release. Your lead in Chat does the same work.",
|
|
19
|
+
session: "Coding sessions are deprecated and will be removed in the next minor release. Queue work as a task instead.",
|
|
20
|
+
};
|
|
@@ -9,10 +9,14 @@ const statements = (id, frozen = false) => {
|
|
|
9
9
|
`CREATE TRIGGER ${prefix}claim BEFORE INSERT ON claim BEGIN SELECT RAISE(ABORT, '${UPDATE_PAUSED} [${id}]'); END`,
|
|
10
10
|
`CREATE TRIGGER ${prefix}mate BEFORE INSERT ON mate_turn BEGIN SELECT RAISE(ABORT, '${UPDATE_PAUSED} [${id}]'); END`,
|
|
11
11
|
`CREATE TRIGGER ${prefix}run BEFORE INSERT ON run ${frozen ? "" : "WHEN NEW.parent_run IS NULL AND NOT EXISTS (SELECT 1 FROM claim WHERE lease_id=NEW.lease_id AND released_at IS NULL) "}BEGIN SELECT RAISE(ABORT, '${UPDATE_PAUSED} [${id}]'); END`,
|
|
12
|
-
// An already-owned
|
|
12
|
+
// An already-owned lead turn may finish its remaining provider steps.
|
|
13
13
|
`CREATE TRIGGER ${prefix}chat BEFORE INSERT ON chat_turn ${frozen ? "" : "WHEN NEW.mate_turn IS NULL "}BEGIN SELECT RAISE(ABORT, '${UPDATE_PAUSED} [${id}]'); END`,
|
|
14
14
|
];
|
|
15
15
|
};
|
|
16
|
+
/** A gate statement as SQLite may keep it: a table RENAME re-quotes names, and a later build may name the lead's turns
|
|
17
|
+
* lead_turn (D5). This build's updater lifts a gate it made under either name. */
|
|
18
|
+
const same = (sql) => sql.replace(/"([A-Za-z_][A-Za-z0-9_]*)"/g, "$1").replace(/\b(?:mate|lead)_turn\b/g, "mate_turn");
|
|
19
|
+
const owns = (wanted, sql) => wanted.map(same).includes(same(String(sql)));
|
|
16
20
|
/** SQLite enforces the gate even for a CLI racing an old in-memory snapshot.
|
|
17
21
|
* Existing leases, replies, heartbeats and task data remain writable. */
|
|
18
22
|
export function installUpdateGate(db, id) {
|
|
@@ -20,7 +24,7 @@ export function installUpdateGate(db, id) {
|
|
|
20
24
|
db.exec("BEGIN IMMEDIATE");
|
|
21
25
|
try {
|
|
22
26
|
const existing = rows(db);
|
|
23
|
-
if (existing.length > 0 && (existing.length !== wanted.length || existing.some(row => ![...wanted, ...statements(id, true)]
|
|
27
|
+
if (existing.length > 0 && (existing.length !== wanted.length || existing.some(row => !owns([...wanted, ...statements(id, true)], row.sql))))
|
|
24
28
|
throw Error("Another or unrecognized update owns admission. Recover that update first.");
|
|
25
29
|
if (existing.length === 0)
|
|
26
30
|
for (const statement of wanted)
|
|
@@ -38,7 +42,7 @@ export function removeUpdateGate(db, id) {
|
|
|
38
42
|
db.exec("BEGIN IMMEDIATE");
|
|
39
43
|
try {
|
|
40
44
|
const existing = rows(db);
|
|
41
|
-
if (existing.some(row => !wanted
|
|
45
|
+
if (existing.some(row => !owns(wanted, row.sql)))
|
|
42
46
|
throw Error("This update does not own the admission pause. Nothing was cleared.");
|
|
43
47
|
removeCodingUpdateGate(db, id);
|
|
44
48
|
for (const row of existing)
|
|
@@ -53,7 +57,7 @@ export function removeUpdateGate(db, id) {
|
|
|
53
57
|
export function updateAdmissionPaused(db) { return rows(db).length > 0; }
|
|
54
58
|
export function updateGateOwned(db, id) {
|
|
55
59
|
const wanted = [...statements(id), ...statements(id, true)], existing = rows(db);
|
|
56
|
-
return existing.length === statements(id).length && existing.every(row => wanted
|
|
60
|
+
return existing.length === statements(id).length && existing.every(row => owns(wanted, row.sql));
|
|
57
61
|
}
|
|
58
62
|
export function activeUpdateWork(db) {
|
|
59
63
|
const count = (sql) => Number(db.prepare(sql).get()?.n ?? 0);
|
package/dist/desktop-update.js
CHANGED
|
@@ -8,6 +8,7 @@ import { readDesktopConfig, desktopServiceCommand, desktopServiceDefinition, ver
|
|
|
8
8
|
import { daemonStatus } from "./daemon.js";
|
|
9
9
|
import { run } from "./exec.js";
|
|
10
10
|
import { readSchemaVersion, SCHEMA_VERSION, Store } from "./store.js";
|
|
11
|
+
import { BASELINE_SCHEMA_VERSION } from "./store-baseline.js";
|
|
11
12
|
import { activeUpdateWork, freezeUpdateGate, installUpdateGate, removeUpdateGate, updateAdmissionPaused } from "./desktop-update-gate.js";
|
|
12
13
|
import { currentDesktopAccess } from "./desktop-access.js";
|
|
13
14
|
import { assertCodingUpdateStopped, backupCodingCatalog, codingCatalogExists, releaseStaleCodingOwner } from "./coding-update.js";
|
|
@@ -125,6 +126,8 @@ function connect(file, readOnly = false, accepts = currentSchemaOnly) {
|
|
|
125
126
|
const schema = readSchemaVersion(db);
|
|
126
127
|
if (!schema.ok || !accepts(schema.version)) {
|
|
127
128
|
db.close();
|
|
129
|
+
if (schema.ok && schema.version !== null && Math.abs(schema.version) < BASELINE_SCHEMA_VERSION)
|
|
130
|
+
throw Error(`This database is schema v${Math.abs(schema.version)}, older than v${BASELINE_SCHEMA_VERSION}: update through 0.9.x first (Toolroll 0.9.54 brings it up to date). The installed app is unchanged.`);
|
|
128
131
|
throw Error("This update needs the current database schema. Use the separate verified migration procedure; the installed app is unchanged.");
|
|
129
132
|
}
|
|
130
133
|
return db;
|
|
@@ -474,7 +477,9 @@ function assertConfig(j) {
|
|
|
474
477
|
}
|
|
475
478
|
function snapshot(db) {
|
|
476
479
|
const result = {};
|
|
477
|
-
|
|
480
|
+
// The lead's messages were mate_message before v117 (D5); a desktop update never migrates, so read whichever is here.
|
|
481
|
+
const messages = db.prepare("SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = 'lead_message'").get() === undefined ? "mate_message" : "lead_message";
|
|
482
|
+
for (const table of ["task", "task_scope", "approver", "run", "artifact", messages, "project"]) {
|
|
478
483
|
const rows = db.prepare(`SELECT * FROM "${table}" ORDER BY rowid`).all();
|
|
479
484
|
result[table] = rows;
|
|
480
485
|
}
|
package/dist/discord-chat.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/** Discord messages and buttons transport the shared assistant's saved actions. */
|
|
2
|
-
import { chatQuestionButtons } from "./
|
|
2
|
+
import { chatQuestionButtons } from "./subagent-question.js";
|
|
3
3
|
import { chatAskButtons } from "./chat-ask.js";
|
|
4
4
|
import { chatFlowButtons } from "./chat-flow.js";
|
|
5
5
|
import { refuseResultShots, resultShotsPruned, shotWaitsUntil } from "./result-shots.js";
|
|
@@ -10,7 +10,7 @@ import { readChatPart } from "./contracts/chat-content.js";
|
|
|
10
10
|
import { readDiscordButtonToken, readDiscordComponentInteraction } from "./contracts/discord-callback.js";
|
|
11
11
|
import { processChatEvent, planChatNotifications, channelAccess, chatObject as object, planRoomMessages, } from "./chat-delivery.js";
|
|
12
12
|
import { chatResultHref } from "./chat-controls.js";
|
|
13
|
-
import {
|
|
13
|
+
import { LEAD_MESSAGE_MAX_CHARS } from "./lead.js";
|
|
14
14
|
import { discordPlain, renderReply } from "./reply-shape.js";
|
|
15
15
|
import { WARM_EMOJI } from "./chat-warmth.js";
|
|
16
16
|
import { proposalPreview, proposalLink, proposalOutcomeText, armedCardText, armedYesLabel, } from "./chat-channel.js";
|
|
@@ -61,7 +61,7 @@ export function receiveDiscord(state, identity, type, raw, now) {
|
|
|
61
61
|
payload = pair
|
|
62
62
|
? { hash: chatHash(pair[1]) }
|
|
63
63
|
: {
|
|
64
|
-
text: body.content.slice(0,
|
|
64
|
+
text: body.content.slice(0, LEAD_MESSAGE_MAX_CHARS + 1),
|
|
65
65
|
originalLength: body.content.length,
|
|
66
66
|
...(Array.isArray(body.attachments) && body.attachments.length
|
|
67
67
|
? {
|
|
@@ -200,7 +200,7 @@ export async function deliverDiscordPart(options) {
|
|
|
200
200
|
return true;
|
|
201
201
|
}
|
|
202
202
|
try {
|
|
203
|
-
const session = event.session === null ? null : store.
|
|
203
|
+
const session = event.session === null ? null : store.getLeadSession(event.session), repos = await channelAccess(shared, binding, session?.ceilingDigest);
|
|
204
204
|
if (event.kind === "notice" && options.canNotify?.() === false)
|
|
205
205
|
return false;
|
|
206
206
|
const content = partContent(row.payload);
|
|
@@ -241,7 +241,7 @@ export async function deliverDiscordPart(options) {
|
|
|
241
241
|
});
|
|
242
242
|
}
|
|
243
243
|
if (content.proposal) {
|
|
244
|
-
const proposal = store.
|
|
244
|
+
const proposal = store.getLeadProposal(content.proposal);
|
|
245
245
|
if (!proposal)
|
|
246
246
|
text = "This proposal is unavailable.";
|
|
247
247
|
else if (proposal.state !== "pending")
|
|
@@ -294,7 +294,7 @@ export async function deliverDiscordPart(options) {
|
|
|
294
294
|
custom_id: `so_${one.token}`,
|
|
295
295
|
}))
|
|
296
296
|
: []),
|
|
297
|
-
// A
|
|
297
|
+
// A subagent's question (v93): its options, then "Answer in words".
|
|
298
298
|
...(content.question
|
|
299
299
|
? chatQuestionButtons(state, row.id, now).map((one) => ({
|
|
300
300
|
type: 2,
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import type { Store } from "./store.js";
|
|
2
|
-
|
|
2
|
+
import { type Html } from "./html.js";
|
|
3
|
+
export declare function discordSettingsHtml(store: Store, dir: string, options?: {
|
|
3
4
|
code?: string;
|
|
4
5
|
problem?: string;
|
|
5
6
|
now?: Date;
|
|
6
7
|
who?: string;
|
|
7
|
-
}):
|
|
8
|
+
}): Html;
|
package/dist/discord-settings.js
CHANGED
|
@@ -1,66 +1,41 @@
|
|
|
1
1
|
import { loadPrimary } from "./webhooks.js";
|
|
2
|
+
import { html, postForm } from "./html.js";
|
|
2
3
|
import { loadDiscordCredentials } from "./discord-api.js";
|
|
3
4
|
import { ChatState } from "./chat-delivery-state.js";
|
|
4
|
-
|
|
5
|
-
.replaceAll("&", "&")
|
|
6
|
-
.replaceAll("<", "<")
|
|
7
|
-
.replaceAll(">", ">")
|
|
8
|
-
.replaceAll('"', """)
|
|
9
|
-
.replaceAll("'", "'");
|
|
10
|
-
export function discordSettingsHtml(store, dir, csrf, options = {}) {
|
|
5
|
+
export function discordSettingsHtml(store, dir, options = {}) {
|
|
11
6
|
const credentials = loadDiscordCredentials(dir), state = new ChatState(store, "discord"), bindings = credentials ? state.bindings(credentials.installation).filter(one => state.live(one)) : [], binding = options.who === undefined ? null : bindings.find(one => one.approver === options.who) ?? null, others = bindings.length - (binding === null ? 0 : 1);
|
|
12
7
|
const runtime = credentials ? state.runtime(credentials.installation) : null;
|
|
13
8
|
const now = options.now ?? new Date(), live = runtime &&
|
|
14
9
|
runtime.leaseUntil !== null &&
|
|
15
10
|
runtime.leaseUntil > now.toISOString() &&
|
|
16
11
|
runtime.connected;
|
|
17
|
-
const
|
|
18
|
-
const
|
|
19
|
-
const
|
|
20
|
-
let content = "";
|
|
12
|
+
const password = html `<label>Your Toolroll password<input style="min-height:44px" type="password" name="password" autocomplete="current-password" required></label>`;
|
|
13
|
+
const post = (action, content) => postForm(`/settings/discord/${action}`, content, { attrs: { class: "card" } });
|
|
14
|
+
const parts = [];
|
|
21
15
|
if (!credentials) {
|
|
22
|
-
|
|
23
|
-
"<p>Manage projects and review results in a private Discord conversation.</p>" +
|
|
24
|
-
'<details open><summary>Create your Discord app</summary><ol><li><a href="https://discord.com/developers/applications" target="_blank" rel="noopener noreferrer">Create an application</a>, then copy its token from the Bot page.</li><li>Keep the Interactions Endpoint URL empty and privileged intents off.</li><li>Under Installation, enable Guild Install with the bot scope and no server permissions. Use its install link to add it to your server, then open a direct message to the bot.</li></ol></details>' +
|
|
25
|
-
post("connect", '<label>Bot token<input style="min-height:44px" type="password" name="bot-token" autocomplete="off" required></label>' +
|
|
26
|
-
password +
|
|
27
|
-
'<p class="meta">The token stays on this installation. Next, pair your own Discord account.</p><button type="submit">Connect Discord</button>');
|
|
16
|
+
parts.push(html `<p>Manage projects and review results in a private Discord conversation.</p>`, html `<details open><summary>Create your Discord app</summary><ol><li><a href="https://discord.com/developers/applications" target="_blank" rel="noopener noreferrer">Create an application</a>, then copy its token from the Bot page.</li><li>Keep the Interactions Endpoint URL empty and privileged intents off.</li><li>Under Installation, enable Guild Install with the bot scope and no server permissions. Use its install link to add it to your server, then open a direct message to the bot.</li></ol></details>`, post("connect", html `<label>Bot token<input style="min-height:44px" type="password" name="bot-token" autocomplete="off" required></label>${password}<p class="meta">The token stays on this installation. Next, pair your own Discord account.</p><button type="submit">Connect Discord</button>`));
|
|
28
17
|
}
|
|
29
18
|
else {
|
|
30
|
-
|
|
19
|
+
parts.push(html `<p><strong>${credentials.workspace}</strong> · ${live ? "Connected" : "Waiting for connection"}</p>`);
|
|
31
20
|
if (runtime?.problem)
|
|
32
|
-
|
|
21
|
+
parts.push(html `<p role="status">${String(runtime.problem)}</p>`);
|
|
33
22
|
if (!live && !runtime?.problem)
|
|
34
|
-
|
|
35
|
-
"<p>Keep the Toolroll worker running to receive Discord messages.</p>";
|
|
23
|
+
parts.push(html `<p>Keep the Toolroll worker running to receive Discord messages.</p>`);
|
|
36
24
|
if (options.code) {
|
|
37
|
-
|
|
38
|
-
"<h2>Pair your account</h2><p>Send this in a direct message to your Toolroll Discord app. It expires in 10 minutes.</p>" +
|
|
39
|
-
`<label>Pairing message<input type="text" readonly value="pair ${escape(options.code)}" autocomplete="off" style="width:100%;max-width:100%;font-size:14px;min-height:44px"></label>` +
|
|
40
|
-
'<a class="button-link" style="min-height:44px;white-space:nowrap" href="/settings/discord">Check connection</a>';
|
|
25
|
+
parts.push(html `<h2>Pair your account</h2><p>Send this in a direct message to your Toolroll Discord app. It expires in 10 minutes.</p>`, html `<label>Pairing message<input type="text" readonly value="pair ${options.code}" autocomplete="off" style="width:100%;max-width:100%;font-size:14px;min-height:44px"></label>`, html `<a class="button-link" style="min-height:44px;white-space:nowrap" href="/settings/discord">Check connection</a>`);
|
|
41
26
|
}
|
|
42
27
|
else if (binding && state.live(binding)) {
|
|
43
28
|
const { pending, dropped: failed } = state.partCounts(binding.id);
|
|
44
|
-
|
|
45
|
-
`<p>
|
|
46
|
-
|
|
47
|
-
'<p><a href="/chat">Open saved chat</a></p>' +
|
|
48
|
-
(loadPrimary(process.env, dir) === "discord"
|
|
49
|
-
? "<p>Task updates are sent here.</p>"
|
|
50
|
-
: post("alerts", '<button type="submit">Send task updates here</button>'));
|
|
29
|
+
parts.push(html `<p>Your Discord account is paired.${others ? ` ${others} teammate${others === 1 ? " is" : "s are"} paired too.` : ""}${pending ? ` ${pending} replies waiting to send.` : ""}${failed ? ` ${failed} replies could not be delivered. Open the saved chat to recover them.` : ""}</p>`, html `<p>Try “What needs my attention?” or “Show the evidence for the latest result.”</p>`, html `<p><a href="/chat">Open saved chat</a></p>`, loadPrimary(process.env, dir) === "discord"
|
|
30
|
+
? html `<p>Task updates are sent here.</p>`
|
|
31
|
+
: post("alerts", html `<button type="submit">Send task updates here</button>`));
|
|
51
32
|
}
|
|
52
33
|
else {
|
|
53
|
-
|
|
54
|
-
(others ? ` ${others} teammate${others === 1 ? " is" : "s are"} already paired.` : "") + "</p>" +
|
|
55
|
-
password +
|
|
56
|
-
'<button type="submit">Create pairing code</button>');
|
|
34
|
+
parts.push(post("pair", html `<h2>Pair your account</h2><p>Your paired Discord account can read your connected projects and confirm proposed changes. Password approvals still open in Toolroll.${others ? ` ${others} teammate${others === 1 ? " is" : "s are"} already paired.` : ""}</p>${password}<button type="submit">Create pairing code</button>`));
|
|
57
35
|
}
|
|
58
36
|
if (binding && state.live(binding) && !options.code)
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
"<details><summary>Connection settings</summary>" +
|
|
62
|
-
post("disconnect", password + '<button type="submit">Disconnect Discord</button>') +
|
|
63
|
-
"</details>";
|
|
37
|
+
parts.push(post("unpair", html `${password}<p class="meta">Unpairing ends every open button in your chat. Teammates are unaffected.</p><button type="submit">Unpair my account</button>`));
|
|
38
|
+
parts.push(html `<details><summary>Connection settings</summary>${post("disconnect", html `${password}<button type="submit">Disconnect Discord</button>`)}</details>`);
|
|
64
39
|
}
|
|
65
|
-
return `<section style="max-width:42rem;overflow-wrap:anywhere"><p><a href="/settings">Settings</a></p><h1>Discord</h1>${options.problem ? `<p class="problem" role="alert">${
|
|
40
|
+
return html `<section style="max-width:42rem;overflow-wrap:anywhere"><p><a href="/settings">Settings</a></p><h1>Discord</h1>${options.problem ? html `<p class="problem" role="alert">${options.problem}</p>` : ""}${parts}<details><summary>Access and setup</summary><p>Private messages and replies use your Toolroll permissions. Shared channels are not supported. Secure review links use this installation’s configured HTTPS console address.</p><p>The worker connects out to Discord. It does not need a public webhook or a Tailscale account.</p></details></section>`;
|
|
66
41
|
}
|
package/dist/dispatch.d.ts
CHANGED
|
@@ -98,5 +98,5 @@ export declare function missingCapability(store: Store, taskRef: number, dispatc
|
|
|
98
98
|
export declare function diagnoseTaskDispatch(store: Store, taskId: string, now: Date, readableRepos?: readonly string[] | null): DispatchDiagnosis | null;
|
|
99
99
|
export declare function diagnosisIsDispatchable(diagnosis: DispatchDiagnosis | null): boolean;
|
|
100
100
|
/** Attach the same lifecycle answer to the bounded fleet snapshot used by
|
|
101
|
-
* both direct chat and the long-running
|
|
101
|
+
* both direct chat and the long-running lead. */
|
|
102
102
|
export declare function withDispatchDiagnoses(store: Store, snapshot: ChatSnapshot, now: Date): ChatSnapshot;
|
package/dist/dispatch.js
CHANGED
|
@@ -330,7 +330,7 @@ export function diagnosisIsDispatchable(diagnosis) {
|
|
|
330
330
|
return diagnosis?.code === "ready" || diagnosis?.code === "planning-ready" || diagnosis?.code === "scouting-ready";
|
|
331
331
|
}
|
|
332
332
|
/** Attach the same lifecycle answer to the bounded fleet snapshot used by
|
|
333
|
-
* both direct chat and the long-running
|
|
333
|
+
* both direct chat and the long-running lead. */
|
|
334
334
|
export function withDispatchDiagnoses(store, snapshot, now) {
|
|
335
335
|
return {
|
|
336
336
|
...snapshot,
|
package/dist/envelope.js
CHANGED
|
@@ -28,7 +28,6 @@ export const CAPABILITIES = [
|
|
|
28
28
|
"output-file", // -o <file> writes the same envelope to a file
|
|
29
29
|
"command-schema/1", // contract --commands dumps the declared command guide
|
|
30
30
|
"skill-guides/1", // skills list / skills get serve version-matched guides
|
|
31
|
-
"session-client/1", // typed operator transport; query the service for actual availability
|
|
32
31
|
];
|
|
33
32
|
/**
|
|
34
33
|
* DOCUMENTED reasons — the curated vocabulary the command guide's
|
|
@@ -71,6 +70,16 @@ export const DOCUMENTED_REASONS = [
|
|
|
71
70
|
"repair-attempts-spent", // the chain's signed attempt cap is spent
|
|
72
71
|
"repair-no-progress", // two consecutive repair attempts failed to shrink the unresolved set
|
|
73
72
|
"repair-refused-integrity", // a refutation named an altered term, not a gap — no automatic repair
|
|
73
|
+
"ambiguous", // a value could mean two things (a lease id or a branch) — refused, never guessed
|
|
74
|
+
"drift", // the branch, pull request or result moved from the gated commit
|
|
75
|
+
"check-failed", // the release check failed; it stays visible and nothing reruns it
|
|
76
|
+
"ci-failed", // a required pull-request check failed or is missing — nothing merged
|
|
77
|
+
"base-moved", // main gained a commit the release branch lacks — nothing merged
|
|
78
|
+
"tree-mismatch", // main's merge commit has a different tree than the gated commit — nothing tagged
|
|
79
|
+
"conflict", // a task or tag exists for a different commit
|
|
80
|
+
"mixed-runtime", // the console, worker and CLI names don't run one build
|
|
81
|
+
"gate-held", // a deployment stopped before its swap and left new work paused — `release --release-gate <id>`
|
|
82
|
+
"after-swap", // the deployment got past stopping the service, so its pause is its own recovery's to lift
|
|
74
83
|
];
|
|
75
84
|
let captured = null;
|
|
76
85
|
let captureHook = null;
|
package/dist/evidence-pack.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { type Filer } from "./approval-policy.js";
|
|
|
2
2
|
import { type AssignmentAccess, type AssignmentSnapshot } from "./assignment.js";
|
|
3
3
|
import type { SealedLedgerEntry, Store } from "./store.js";
|
|
4
4
|
import type { LedgerChainReport } from "./ledger-chain.js";
|
|
5
|
+
import { type Html } from "./html.js";
|
|
5
6
|
export declare const EVIDENCE_PACK_FORMAT = "standing-orders/evidence-pack/v1";
|
|
6
7
|
/** How to recheck one entry's seal, for whoever reads the JSON. */
|
|
7
8
|
export declare const SEAL_RECIPE = "hash = sha256(prev + \"\\n\" + JSON.stringify([id, at, actor, repo, taskId, runId, action, outcome, source, detail]))";
|
|
@@ -179,7 +180,7 @@ export declare function ledgerExportChunks(store: Store, range: {
|
|
|
179
180
|
}, access: AssignmentAccess, who: string, now: Date, evidenceRoot: string): Generator<string, void, undefined>;
|
|
180
181
|
export declare const EVIDENCE_PACK_CSS: string;
|
|
181
182
|
/** The pack as a page: the same facts, in the order an auditor reads them. No script. */
|
|
182
|
-
export declare function evidencePackHtml(pack: EvidencePack):
|
|
183
|
+
export declare function evidencePackHtml(pack: EvidencePack): Html;
|
|
183
184
|
/** The page as a file on its own (the CLI's --html): the same facts with just enough style to print. */
|
|
184
185
|
export declare function standaloneEvidenceHtml(pack: EvidencePack): string;
|
|
185
186
|
export {};
|