toolroll 0.9.85 → 0.9.87
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 +83 -0
- package/dist/agent-fence.d.ts +6 -2
- package/dist/agent-fence.js +3 -2
- package/dist/agents-board.d.ts +12 -0
- package/dist/agents-board.js +26 -0
- package/dist/approval-rules-ui.d.ts +4 -1
- package/dist/approval-rules-ui.js +31 -15
- package/dist/assignment-ui.js +1 -1
- package/dist/assignment.js +4 -3
- package/dist/backup-ui.d.ts +5 -4
- package/dist/backup-ui.js +65 -32
- package/dist/browser/terminal.css +1 -1
- package/dist/browser/terminal.js +57 -54
- package/dist/browser/workspace.css +2 -2
- package/dist/browser/workspace.js +35 -68
- package/dist/browser-crew.js +1 -1
- package/dist/browser-workspace.d.ts +363 -177
- package/dist/browser-workspace.js +10 -9
- package/dist/chat-actions.d.ts +11 -1
- package/dist/chat-actions.js +53 -1
- package/dist/chat-channel.js +1 -0
- package/dist/chat-controls.d.ts +1 -1
- package/dist/chat-controls.js +1 -1
- package/dist/chat-quiet.js +3 -2
- package/dist/chat-settings-page.d.ts +29 -9
- package/dist/chat-settings-page.js +59 -28
- package/dist/check-levels-ui.d.ts +2 -1
- package/dist/check-levels-ui.js +67 -58
- 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/cli.d.ts +43 -0
- package/dist/contracts/cli.js +4 -0
- package/dist/contracts/console-api.d.ts +4 -1
- package/dist/contracts/console-api.js +4 -1
- 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 +21 -0
- package/dist/contracts/lead-tools.js +2 -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/coordinator.js +1 -0
- package/dist/credentials-ui.d.ts +5 -3
- package/dist/credentials-ui.js +58 -31
- package/dist/deploy-gate.js +4 -0
- package/dist/design/kit.css +685 -0
- package/dist/design/kit.d.ts +208 -0
- package/dist/design/kit.js +177 -0
- package/dist/design/tokens.css +19 -1
- package/dist/discord-settings.js +8 -4
- package/dist/dispatch.d.ts +3 -0
- package/dist/dispatch.js +4 -1
- package/dist/export-ui.d.ts +6 -4
- package/dist/export-ui.js +18 -8
- package/dist/flow-browser.d.ts +103 -0
- package/dist/flow-browser.js +204 -0
- package/dist/flow-changed.d.ts +14 -0
- package/dist/flow-changed.js +53 -0
- 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-gallery-ui.d.ts +41 -4
- package/dist/flow-gallery-ui.js +95 -63
- 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-starters-ui.d.ts +3 -9
- package/dist/flow-starters-ui.js +12 -23
- package/dist/flow-steps.d.ts +9 -1
- package/dist/flow-steps.js +55 -5
- package/dist/flow-triggers.js +55 -0
- package/dist/flow-unattended-words.d.ts +20 -0
- package/dist/flow-unattended-words.js +24 -0
- package/dist/flow-unattended.d.ts +9 -5
- package/dist/flow-unattended.js +45 -23
- package/dist/flows-cli.d.ts +19 -0
- package/dist/flows-cli.js +54 -5
- package/dist/flows-ui.d.ts +12 -6
- package/dist/flows-ui.js +152 -32
- package/dist/flows.js +5 -2
- package/dist/integrations-ui.d.ts +6 -4
- package/dist/integrations-ui.js +34 -40
- package/dist/integrations.d.ts +2 -2
- package/dist/integrations.js +4 -4
- package/dist/kits-ui.d.ts +8 -10
- package/dist/kits-ui.js +29 -33
- package/dist/kits.js +1 -1
- package/dist/knowledge-ui.js +76 -19
- package/dist/lead-tools.js +35 -6
- package/dist/lead-voice.js +16 -5
- package/dist/ledger-view.d.ts +2 -0
- package/dist/ledger-view.js +41 -38
- package/dist/models-ui.d.ts +8 -3
- package/dist/models-ui.js +82 -59
- package/dist/monitoring-ui.d.ts +4 -2
- package/dist/monitoring-ui.js +44 -13
- package/dist/needs-you.d.ts +1 -1
- package/dist/needs-you.js +8 -0
- package/dist/operate-remote-arguments.js +1 -0
- package/dist/operate-remote.js +1 -1
- package/dist/operate.d.ts +1 -1
- package/dist/operate.js +249 -6
- package/dist/passwordless.d.ts +1 -1
- package/dist/passwordless.js +1 -1
- package/dist/people-audit-ui.d.ts +2 -1
- package/dist/people-audit-ui.js +25 -23
- package/dist/policy-ui.d.ts +3 -2
- package/dist/policy-ui.js +27 -21
- package/dist/policy.d.ts +3 -0
- package/dist/policy.js +14 -1
- package/dist/project-delete-ui.d.ts +4 -2
- package/dist/project-delete-ui.js +135 -126
- package/dist/project-delete.js +7 -3
- package/dist/project-knowledge.d.ts +10 -10
- package/dist/publish.d.ts +11 -0
- package/dist/publish.js +16 -3
- package/dist/pull-request-flow.js +35 -4
- package/dist/pull-request-ui.d.ts +2 -1
- package/dist/pull-request-ui.js +39 -28
- package/dist/recipe-ui.d.ts +4 -2
- package/dist/recipe-ui.js +14 -4
- package/dist/release-adapters.d.ts +3 -0
- package/dist/release-adapters.js +22 -2
- package/dist/release-cli.js +81 -9
- package/dist/release.d.ts +21 -0
- package/dist/release.js +40 -4
- package/dist/releases.js +1 -1
- package/dist/request-budget-ui.d.ts +4 -2
- package/dist/request-budget-ui.js +30 -19
- package/dist/result-follow-ups.js +4 -0
- package/dist/retention-ui.d.ts +4 -3
- package/dist/retention-ui.js +15 -12
- package/dist/scope.d.ts +8 -0
- package/dist/scope.js +13 -0
- package/dist/serve.d.ts +0 -1
- package/dist/serve.js +51 -7
- package/dist/server/agents-computers.d.ts +9 -0
- package/dist/server/agents-computers.js +67 -0
- package/dist/server/chat.js +20 -18
- package/dist/server/chrome.d.ts +1 -1
- package/dist/server/chrome.js +19 -9
- package/dist/server/console.css +31 -2
- package/dist/server/flows.js +79 -36
- package/dist/server/home.d.ts +35 -0
- package/dist/server/home.js +104 -0
- package/dist/server/http.d.ts +3 -0
- package/dist/server/http.js +5 -0
- package/dist/server/kit-standalone.d.ts +22 -0
- package/dist/server/kit-standalone.js +69 -0
- package/dist/server/kit.d.ts +405 -0
- package/dist/server/kit.js +361 -0
- package/dist/server/pages.d.ts +2 -1
- package/dist/server/pages.js +213 -174
- package/dist/server/people-tokens.js +26 -85
- package/dist/server/render-history.d.ts +51 -0
- package/dist/server/render-history.js +228 -0
- package/dist/server/render-new-task.d.ts +29 -0
- package/dist/server/render-new-task.js +96 -0
- package/dist/server/render-next.d.ts +63 -0
- package/dist/server/render-next.js +109 -0
- package/dist/server/render-pages.d.ts +35 -190
- package/dist/server/render-pages.js +154 -563
- package/dist/server/render-people.d.ts +24 -3
- package/dist/server/render-people.js +93 -72
- package/dist/server/render-projects.d.ts +103 -0
- package/dist/server/render-projects.js +247 -0
- package/dist/server/render-results.d.ts +5 -24
- package/dist/server/render-results.js +48 -185
- package/dist/server/render-settings.d.ts +5 -74
- package/dist/server/render-settings.js +102 -493
- package/dist/server/render-tasks.d.ts +43 -5
- package/dist/server/render-tasks.js +131 -91
- package/dist/server/route-table.js +31 -5
- package/dist/server/settings.js +276 -255
- package/dist/server/task-views.d.ts +8 -0
- package/dist/server/task-views.js +90 -2
- package/dist/server/tasks.d.ts +18 -0
- package/dist/server/tasks.js +148 -41
- package/dist/server/terminals.js +1 -1
- package/dist/server/welcome.d.ts +22 -0
- package/dist/server/welcome.js +69 -0
- package/dist/settings-groups-ui.d.ts +279 -0
- package/dist/settings-groups-ui.js +615 -0
- package/dist/settings-kit.d.ts +42 -6
- package/dist/settings-kit.js +69 -7
- package/dist/settings-proofs.js +1 -0
- package/dist/setup-guide.d.ts +2 -2
- package/dist/skills-ui.js +59 -7
- package/dist/slack-settings.js +12 -5
- package/dist/spend-ui.d.ts +45 -26
- package/dist/spend-ui.js +124 -56
- package/dist/sso-ui.d.ts +5 -2
- package/dist/sso-ui.js +63 -31
- package/dist/storage-ui.d.ts +3 -2
- package/dist/storage-ui.js +56 -50
- package/dist/store.d.ts +182 -5
- package/dist/store.js +512 -38
- package/dist/surface.js +23 -3
- 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/teams-settings.d.ts +2 -1
- package/dist/teams-settings.js +24 -41
- package/dist/telegram-settings.d.ts +0 -4
- package/dist/telegram-settings.js +52 -25
- package/dist/tidy.d.ts +130 -0
- package/dist/tidy.js +503 -0
- package/dist/toolroll-update-ui.d.ts +8 -4
- package/dist/toolroll-update-ui.js +55 -45
- package/dist/tools-ui.d.ts +5 -3
- package/dist/tools-ui.js +107 -42
- package/dist/work-index.d.ts +24 -0
- package/dist/work-index.js +56 -30
- package/dist/workspace-ui.d.ts +1 -1
- package/dist/workspace-ui.js +8 -4
- package/package.json +1 -1
|
@@ -362,12 +362,6 @@ export declare function evidenceWords(kind: string): string;
|
|
|
362
362
|
* orphaned run keeps saying what actually became of it. */
|
|
363
363
|
export declare function runOutcomeBadge(run: Run, live: boolean): Html;
|
|
364
364
|
export declare const runNoun: (run: Pick<Run, "role">) => string;
|
|
365
|
-
export declare function runsPage(chrome: Chrome, rows: (Run & {
|
|
366
|
-
taskId: string;
|
|
367
|
-
})[], liveIds: ReadonlySet<number>, nextCursor: number | null, verdicts?: Map<number, {
|
|
368
|
-
verdict: ProofVerdict;
|
|
369
|
-
matrix?: CriterionMatrixRow[];
|
|
370
|
-
}>, accepted?: ReadonlySet<number>): Screen;
|
|
371
365
|
/** The evidence bundle (Priority 2): the closed machine-authored verdict,
|
|
372
366
|
* the agent's proof (or why it cannot be shown), the plane's own re-run
|
|
373
367
|
* check, and every validated screenshot — each row labeled by source so
|
|
@@ -732,24 +726,11 @@ export declare function resultPrimaryAction(detail: ResultDetail, o: ResultPanel
|
|
|
732
726
|
/** The run's route provenance in plain words (v47): the exact agent it
|
|
733
727
|
* spent as, in which role, and how that agent was chosen. */
|
|
734
728
|
export declare function runAgentWords(route: RouteStamp | null | undefined): string | null;
|
|
735
|
-
|
|
736
|
-
export declare function
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
createdAt: string;
|
|
741
|
-
}[], csrf?: string, comments?: DiffComment[], ciRepair?: {
|
|
742
|
-
pr: number;
|
|
743
|
-
} | null, liveScript?: string, peekable?: boolean, running?: boolean, editor?: {
|
|
744
|
-
worktree: string;
|
|
745
|
-
} | null, editorToggle?: {
|
|
746
|
-
on: boolean;
|
|
747
|
-
} | null, noted?: boolean, structuredHandoff?: StructuredHandoffView | null, proofBundle?: ProofBundleView | null, route?: RouteStamp | null, publicationRow?: Publication | null, review?: ReviewFacts | null, result?: {
|
|
748
|
-
detail: ResultDetail;
|
|
749
|
-
tab: ResultTab;
|
|
750
|
-
user: string;
|
|
751
|
-
requestToken: string;
|
|
752
|
-
} | null, sourceDigest?: string | null): Screen;
|
|
729
|
+
/** A run's outcome in the kit's tones: built or no change finished, failed or refused failed, anything else neutral. */
|
|
730
|
+
export declare function runOutcomeChip(run: Pick<Run, "outcome" | "reason" | "role">, live: boolean): Html;
|
|
731
|
+
/** A run's facts as the kit's facts list: how it ended, who ran it where, when, what it cost and where it ended. The
|
|
732
|
+
* live poll (`?fragment=facts`) swaps the same list in place. (The page's header names the run and its task.) */
|
|
733
|
+
export declare function runFactsRows(run: Run, _taskId: string, live: boolean, route?: RouteStamp | null): Html;
|
|
753
734
|
/**
|
|
754
735
|
* Click-to-prefill (arc 6, finding 4): client-side FORM mutation, named as
|
|
755
736
|
* such — normal viewing stays the default; "Annotate" reveals line pins.
|
|
@@ -27,6 +27,7 @@ import { createHash, randomBytes } from "node:crypto";
|
|
|
27
27
|
import { buildsViews, oneLineOf, projectChip, safePrUrl, screen, sentenceCase, strokeIcon, when, whenTime } from "./chrome.js";
|
|
28
28
|
import { chatResultHref, reviewHref, taskChatHref, taskHref } from "./http.js";
|
|
29
29
|
import { attributes, html, htmlString, joinHtml, postForm, reauth } from "../html.js";
|
|
30
|
+
import { chip, facts } from "./kit.js";
|
|
30
31
|
import { publicationFactsOf, statusActionHref, statusLineHtml } from "./render-tasks.js";
|
|
31
32
|
export const RUNS_PAGE = 50;
|
|
32
33
|
/**
|
|
@@ -948,27 +949,6 @@ export function runOutcomeBadge(run, live) {
|
|
|
948
949
|
: html `<span class="badge badge-${run.outcome ?? "cut"}">${sentenceCase(run.outcome ?? "never finished")}</span>`;
|
|
949
950
|
}
|
|
950
951
|
export const runNoun = (run) => run.role === "planner" ? "plan" : run.role === "reviewer" ? "review" : run.role === "scout" ? "report" : "build";
|
|
951
|
-
export function runsPage(chrome, rows, liveIds, nextCursor, verdicts = new Map(), accepted = new Set()) {
|
|
952
|
-
const list = rows.length === 0
|
|
953
|
-
? html `<p class="meta">No builds yet \u2014 they appear once an approved task is dispatched.</p>`
|
|
954
|
-
: joinHtml(rows
|
|
955
|
-
.map(run => {
|
|
956
|
-
const verdict = verdicts.get(run.id)?.verdict ?? null;
|
|
957
|
-
const needsVerification = (verdict === "short" || verdict === "refuted") && !accepted.has(run.id)
|
|
958
|
-
? html ` <span class="badge badge-failed">${verdict === "refuted" ? "conflicting evidence" : "missing evidence"}</span>`
|
|
959
|
-
: "";
|
|
960
|
-
return html `<p class="row"><a href="/r/${run.id}" class="mono">#${run.id}</a> <a href="${taskHref(run.taskId)}" class="mono">${run.taskId}</a> ${[
|
|
961
|
-
runOutcomeBadge(run, liveIds.has(run.id)),
|
|
962
|
-
run.qualityMode === "strict" ? html ` <span class="badge">Strict review</span>` : "",
|
|
963
|
-
needsVerification,
|
|
964
|
-
criterionMatrixSummary(verdicts.get(run.id)?.matrix ?? []),
|
|
965
|
-
run.provider === "claude" ? "" : html ` <span class="meta mono">${run.provider}</span>`,
|
|
966
|
-
html `<span class="right meta mono">${whenTime(run.startedAt)}${run.providerStartedAt === null && run.tokensIn === null && run.tokensOut === null && run.costUsd === null ? "" : ` \u00b7 ${runCostWords(run, liveIds.has(run.id))}`}</span></p>`,
|
|
967
|
-
]}`;
|
|
968
|
-
}), "\n");
|
|
969
|
-
const older = nextCursor === null ? "" : html `<p><a href="/runs?before=${nextCursor}">older →</a></p>`;
|
|
970
|
-
return screen("builds", joinHtml([html `<h1>Builds <a class="badge" href="/peek">Peek at the live ones \u2192</a></h1>`, buildsViews("builds"), html `<p class="hint">one build = one attempt by an agent to complete a task, on its own branch</p>`, list, older], "\n"), { chrome });
|
|
971
|
-
}
|
|
972
952
|
/** What a scout found, each with its link and picture, then any screenshot no item shows. Every link is the cited
|
|
973
953
|
* http(s) address the report parser admitted; every picture is served from verified evidence. */
|
|
974
954
|
export function reportItemsHtml(items, shots, runId) {
|
|
@@ -2096,173 +2076,56 @@ export function runAgentWords(route) {
|
|
|
2096
2076
|
: "recommended";
|
|
2097
2077
|
return `${route.provider}${route.model === null ? "" : ` · ${route.model}`} as the ${role} — ${how}`;
|
|
2098
2078
|
}
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
],
|
|
2079
|
+
/** A run's outcome in the kit's tones: built or no change finished, failed or refused failed, anything else neutral. */
|
|
2080
|
+
export function runOutcomeChip(run, live) {
|
|
2081
|
+
if (live)
|
|
2082
|
+
return chip("Running", "live");
|
|
2083
|
+
if (run.role === "planner" && run.reason === "plan-drafted")
|
|
2084
|
+
return chip("Planned", "done");
|
|
2085
|
+
if (run.reason === "interrupted")
|
|
2086
|
+
return chip("Interrupted");
|
|
2087
|
+
const word = sentenceCase(run.outcome ?? "never finished");
|
|
2088
|
+
return chip(word, run.outcome === "built" || run.outcome === "no-change" ? "done" : run.outcome === "failed" || run.outcome === "refused" ? "failed" : "");
|
|
2089
|
+
}
|
|
2090
|
+
/** How long a finished run ran, in whole minutes (seconds under one). */
|
|
2091
|
+
function ranWords(run) {
|
|
2092
|
+
if (run.startedAt === null || run.finishedAt === null)
|
|
2093
|
+
return null;
|
|
2094
|
+
const ms = Date.parse(run.finishedAt) - Date.parse(run.startedAt);
|
|
2095
|
+
if (!Number.isFinite(ms) || ms < 0)
|
|
2096
|
+
return null;
|
|
2097
|
+
return ms < 60_000 ? `${Math.max(1, Math.round(ms / 1000))} s` : ms < 3_600_000 ? `${Math.round(ms / 60_000)} min` : `${Math.floor(ms / 3_600_000)} h ${Math.round((ms % 3_600_000) / 60_000)} min`;
|
|
2098
|
+
}
|
|
2099
|
+
/** A run's facts as the kit's facts list: how it ended, who ran it where, when, what it cost and where it ended. The
|
|
2100
|
+
* live poll (`?fragment=facts`) swaps the same list in place. (The page's header names the run and its task.) */
|
|
2101
|
+
export function runFactsRows(run, _taskId, live, route = null) {
|
|
2102
|
+
const mono = (value) => html `<span class="k-mono">${value}</span>`;
|
|
2103
|
+
const rows = [
|
|
2104
|
+
["Outcome", runOutcomeChip(run, live)],
|
|
2105
|
+
["Step", live && run.phase !== null ? phaseWords(run.phase) : null],
|
|
2106
|
+
["Reason", run.reason === null ? null : isInternalErrorReason(run.reason) ? "stopped with an internal error (below)" : reasonWords(run.reason)],
|
|
2107
|
+
["Agent", runAgentWords(route) ?? `${run.provider}${run.model === null ? "" : ` · ${run.model}`}`],
|
|
2108
|
+
["Quality", qualityModeTitle(run.qualityMode ?? "default")],
|
|
2109
|
+
["Computer", run.runner === null ? null : mono(run.runner)],
|
|
2110
|
+
["Branch", run.branch === null ? null : mono(run.branch)],
|
|
2111
|
+
["Started", run.startedAt === null ? null : whenTime(run.startedAt)],
|
|
2112
|
+
["Agent started", run.providerStartedAt === null ? null : whenTime(run.providerStartedAt)],
|
|
2113
|
+
["Finished", run.finishedAt === null ? null : whenTime(run.finishedAt)],
|
|
2114
|
+
live && run.startedAt !== null ? ["Elapsed", html `<time class="k-num" data-elapsed-since="${run.startedAt}"></time>`] : ["Ran", ranWords(run)],
|
|
2115
|
+
["Starting point", run.baseRevision === null ? null : mono(run.baseRevision.slice(0, 12))],
|
|
2116
|
+
["Commit", run.headRevision === null ? null : mono(run.headRevision.slice(0, 12))],
|
|
2117
|
+
["Tokens", run.tokensIn === null && run.tokensOut === null ? null : html `<span class="k-num">${(run.tokensIn ?? 0).toLocaleString()} in · ${(run.tokensOut ?? 0).toLocaleString()} out</span>`],
|
|
2118
|
+
// Auth is part of the economic fact: Claude's subscription harness reports an API-price equivalent, not a separate
|
|
2119
|
+
// API-key charge.
|
|
2120
|
+
["Spend", run.providerStartedAt === null && run.tokensIn === null && run.tokensOut === null && run.costUsd === null ? null : runCostWords(run, live)],
|
|
2125
2121
|
];
|
|
2126
|
-
const
|
|
2127
|
-
|
|
2128
|
-
: "";
|
|
2129
|
-
return html `${joinHtml(facts
|
|
2130
|
-
.filter((fact) => fact[1] !== null && fact[1] !== "")
|
|
2131
|
-
.map(([label, value, mono]) => html `<p class="row"><span class="meta" style="min-width:8.5rem">${label}</span> <span${mono === true ? html ` class="mono"` : ""}>${value}</span></p>`), "\n")}${elapsed}${
|
|
2122
|
+
const shown = rows.filter((row) => row[1] !== null && row[1] !== "");
|
|
2123
|
+
return html `${facts(shown)}${
|
|
2132
2124
|
// Machine output (a stack trace, a path, "Error:" text) reads as an internal error everywhere else; its detail is here, as recorded.
|
|
2133
2125
|
run.reason !== null && isInternalErrorReason(run.reason)
|
|
2134
|
-
? html `<p class="
|
|
2126
|
+
? html `<p class="k-note">Recorded error</p><pre class="k-mono h-pre" id="run-reason-detail">${run.reason}</pre>`
|
|
2135
2127
|
: ""}`;
|
|
2136
2128
|
}
|
|
2137
|
-
export function runPage(chrome, run, taskId, artifacts, terminal = null, notes = [], csrf = "", comments = [], ciRepair = null, liveScript, peekable = false, running = false, editor = null, editorToggle = null, noted = false, structuredHandoff = null, proofBundle = null, route = null, publicationRow = null, review = null, result = null, sourceDigest = null) {
|
|
2138
|
-
const rows = runFactsRows(run, taskId, running, route);
|
|
2139
|
-
// The live peek region (A2): the poller fills it only on a serve that
|
|
2140
|
-
// asserted its runner. Without the assertion the section still appears
|
|
2141
|
-
// for a running build and says honestly why it is empty \u2014 a page that
|
|
2142
|
-
// silently lacked the region while the task screen promised a live view
|
|
2143
|
-
// read as broken (round-4, A1).
|
|
2144
|
-
const peek = !running
|
|
2145
|
-
? ""
|
|
2146
|
-
: peekable
|
|
2147
|
-
? html `<h2>What is changing right now</h2><div id="run-peek"><p class="meta">Watching\u2026 the first look lands within 15 seconds</p></div><p class="meta" id="run-peek-stamp"></p>`
|
|
2148
|
-
: html `<h2>What is changing right now</h2><p class="meta">The live file view is off \u2014 start serve with ${"--runner <name>"} naming this machine's worker, and it appears here</p>`;
|
|
2149
|
-
// The live transcript (arc 1): the agent's own words, streamed to a file
|
|
2150
|
-
// beside the run and polled as raw text. Honesty stated on the surface:
|
|
2151
|
-
// this is display only, and the machine running the agent could alter it.
|
|
2152
|
-
const transcript = !running
|
|
2153
|
-
? ""
|
|
2154
|
-
: !peekable
|
|
2155
|
-
? html `<h2>What the agent is saying</h2><p class="meta">The live transcript is off \u2014 start serve with ${"--runner <name>"} naming this machine's worker, and it appears here</p>`
|
|
2156
|
-
: run.provider !== "claude"
|
|
2157
|
-
? html `<h2>What the agent is saying</h2><p class="meta">The live transcript needs the claude harness for now \u2014 this build runs on ${run.provider}</p>`
|
|
2158
|
-
: html `<h2>What the agent is saying</h2><p class="meta">Display only \u2014 this is not evidence, and the machine running the agent could alter it</p><pre id="live-transcript" class="mono" style="max-height:24rem;overflow:auto;white-space:pre-wrap"></pre><p class="meta" id="live-transcript-state"></p>`;
|
|
2159
|
-
const resultSummary = structuredHandoff?.conclusion ?? run.handoff;
|
|
2160
|
-
const resultList = (label, items) => items.length === 0
|
|
2161
|
-
? ""
|
|
2162
|
-
: html `<div class="result-section"><strong>${label}</strong><ul>${items.map(one => html `<li>${one}</li>`)}</ul></div>`;
|
|
2163
|
-
const handoff = resultSummary === null
|
|
2164
|
-
? ""
|
|
2165
|
-
: html `<section class="card result-card"><h2>Result</h2><p class="recap">${resultSummary}</p>${structuredHandoff === null
|
|
2166
|
-
? ""
|
|
2167
|
-
: [resultList("completed", structuredHandoff.changes),
|
|
2168
|
-
resultList("checks reported by the agent", structuredHandoff.verification),
|
|
2169
|
-
resultList("follow-up", structuredHandoff.followUps)]}</section>`;
|
|
2170
|
-
const evidence = artifacts.length === 0
|
|
2171
|
-
? ""
|
|
2172
|
-
: html `<details class="evidence-files"><summary>Saved files <span class="meta">(${artifacts.length})</span></summary><ul>${artifacts
|
|
2173
|
-
.map(artifact => html `<li><a href="/r/${run.id}/evidence/${artifact.id}">${evidenceWords(artifact.kind)}</a> <span class="meta" title="${artifact.bytesStored} bytes stored${artifact.truncated ? ` of ${artifact.bytesOriginal}` : ""}">${artifact.truncated ? `${humanBytes(artifact.bytesStored)} of ${humanBytes(artifact.bytesOriginal)} · partial` : humanBytes(artifact.bytesStored)}</span></li>`)}</ul></details>`;
|
|
2174
|
-
// Review comments on the immutable terminal diff (M6.8): listed, added,
|
|
2175
|
-
// and sealed into ONE unapproved revision task. The seal is deliberately
|
|
2176
|
-
// plain — the ceremony lives on the revision task's approval screen,
|
|
2177
|
-
// which restates the batch; this button only creates the unapproved task.
|
|
2178
|
-
const hasTerminalDiff = terminal !== null && terminal.patch !== null && !("problem" in terminal.patch);
|
|
2179
|
-
const commentPathWords = (path, line) => {
|
|
2180
|
-
const shown = `${path}${line === null ? "" : `:${line}`}`;
|
|
2181
|
-
const href = editor === null ? null : editorFileHref(editor.worktree, path, line);
|
|
2182
|
-
return href === null
|
|
2183
|
-
? html `<span class="mono">${shown}</span> `
|
|
2184
|
-
: html `<a class="mono" href="${href}">${shown}</a> `;
|
|
2185
|
-
};
|
|
2186
|
-
const commentRows = comments
|
|
2187
|
-
.map(one => html `<div class="diff-comment"><span class="diff-comment-pin" aria-hidden="true"></span><p>${one.path === null ? "" : commentPathWords(one.path, one.line)}${one.note}</p><span class="meta">${one.author} · ${whenTime(one.createdAt)}</span></div>`);
|
|
2188
|
-
const commentForm = csrf === "" || !hasTerminalDiff
|
|
2189
|
-
? null
|
|
2190
|
-
: postForm(`/r/${run.id}/comment`, html `<div class="diff-comment-target"><label>File<input type="text" name="path" placeholder="select a line above" aria-label="file" class="mono"></label><label>Line<input type="text" name="line" placeholder="—" aria-label="line" inputmode="numeric"></label></div><label>Change requested<textarea name="note" rows="2" maxlength="${LIMITS.note}" placeholder="Explain what should change and why" aria-label="review comment" aria-describedby="comment-note-limit"${noted ? " autofocus" : ""}></textarea></label><span class="meta diff-comment-limit" id="comment-note-limit">up to ${LIMITS.note} characters</span><button type="submit">Add annotation</button>`, { attrs: { class: "card diff-comment-form", id: "comment-form" } });
|
|
2191
|
-
// The device-side half of the editor-link activation (arc 6, finding 1):
|
|
2192
|
-
// rendered only when the server capability exists and this run belongs
|
|
2193
|
-
// to this machine's runner — the person at the browser flips it.
|
|
2194
|
-
const editorToggleForm = editorToggle === null || csrf === ""
|
|
2195
|
-
? ""
|
|
2196
|
-
: postForm("/session/editor-links", html `<button type="submit">${editorToggle.on ? "stop opening files in VS Code from this device" : "open files in VS Code from this device"}</button><span class="meta"> — only useful when this browser runs on the machine that holds the worktrees</span>`, { attrs: { class: "row" }, returnTo: `/r/${run.id}`, hidden: { on: editorToggle.on ? "0" : "1" } });
|
|
2197
|
-
const reviseForm = csrf === "" || comments.length === 0
|
|
2198
|
-
? ""
|
|
2199
|
-
: postForm(`/r/${run.id}/revise`, html `${revisionSealFields(comments, sourceDigest)}<div><strong>${comments.length} annotation${comments.length === 1 ? "" : "s"} ready</strong><span class="meta">Creates one revision carrying this exact batch. You review its scope before anything builds.</span></div><button type="submit">Create revision from annotations</button>`, { attrs: { class: "card revision-from-comments" } });
|
|
2200
|
-
// CI repair, suggestion-first (M8.18): the observed red episode earns a
|
|
2201
|
-
// button; the button drafts ONE unapproved task; a person approves it.
|
|
2202
|
-
const repairCard = ciRepair === null || csrf === ""
|
|
2203
|
-
? ""
|
|
2204
|
-
: html `<div class="card"><p><strong>CI is failing on PR #${ciRepair.pr}</strong> <span class="meta">observed by the episode watcher</span></p>${postForm(`/r/${run.id}/draft-repair`, html `<button type="submit">Draft a repair task</button><span class="meta"> — one unapproved task; you approve its scope before anything builds</span>`)}</div>`;
|
|
2205
|
-
const reviewCard = html `${commentRows.length === 0 && commentForm === null ? "" : html `<h2 id="review">Review and revise</h2><p class="meta">Annotate the diff above. When the batch is ready, create one scoped revision task from it.</p>${commentRows.length === 0 ? "" : html `<div class="diff-comments">${joinHtml(commentRows, "\n")}</div>`}${commentForm}${reviseForm}${editorToggleForm}`}${repairCard}`;
|
|
2206
|
-
const noteRows = joinHtml(notes.map(one => html `<p class="row"><span class="meta">${one.author} · ${whenTime(one.createdAt)}</span> ${one.note}</p>`), "\n");
|
|
2207
|
-
const noteForm = csrf === ""
|
|
2208
|
-
? null
|
|
2209
|
-
: postForm(`/r/${run.id}/note`, html `<input type="text" name="note" placeholder="a note for whoever reads this run next" aria-label="run note" style="width:100%;max-width:28rem"><button type="submit">Add note</button>`, { attrs: { class: "row" } });
|
|
2210
|
-
const notesCard = notes.length === 0 && noteForm === null ? "" : html `<h2>Operator notes</h2>${noteRows}${noteForm}`;
|
|
2211
|
-
// Outcome first (UI polish 2026-09-13): a finished build leads with its
|
|
2212
|
-
// result, proof, and diff; the machine facts fold under "Build details".
|
|
2213
|
-
// A live build keeps the facts open — they are what a watcher polls.
|
|
2214
|
-
const facts = running
|
|
2215
|
-
? html `<div id="run-facts">${rows}</div><p class="meta" id="run-facts-stamp"></p>`
|
|
2216
|
-
: html `<details class="run-facts-details"><summary>Run record<span class="meta">${[run.runner, run.provider, run.outcome ?? "never finished"].join(" · ")}</span></summary><div id="run-facts">${rows}</div></details>`;
|
|
2217
|
-
// A finished result (package 3) is the ONE shared panel — Summary /
|
|
2218
|
-
// Changes / Checks with Request changes beside it — the same markup the
|
|
2219
|
-
// review cockpit and the chat's result view render. Every other run
|
|
2220
|
-
// (live, failed, interrupted) keeps its record-by-record page.
|
|
2221
|
-
const resultPanel = result === null
|
|
2222
|
-
? null
|
|
2223
|
-
: resultPanelHtml(result.detail, {
|
|
2224
|
-
place: "run",
|
|
2225
|
-
tab: result.tab,
|
|
2226
|
-
csrf,
|
|
2227
|
-
user: result.user,
|
|
2228
|
-
noted,
|
|
2229
|
-
requestToken: result.requestToken,
|
|
2230
|
-
hrefFor: one => (one === "summary" ? `/r/${run.id}` : `/r/${run.id}?tab=${one}`),
|
|
2231
|
-
returnTo: `/r/${run.id}?record=1`,
|
|
2232
|
-
back: null,
|
|
2233
|
-
});
|
|
2234
|
-
return screen(`build #${run.id}`, joinHtml([
|
|
2235
|
-
html `<h1>Build #${run.id} <span class="meta"><a href="${taskHref(taskId)}">${taskId}</a></span></h1>`,
|
|
2236
|
-
running ? facts : "",
|
|
2237
|
-
transcript,
|
|
2238
|
-
peek,
|
|
2239
|
-
...(resultPanel === null
|
|
2240
|
-
? [
|
|
2241
|
-
handoff,
|
|
2242
|
-
evidenceBundleCard(proofBundle, run, publicationFactsOf(publicationRow), review),
|
|
2243
|
-
terminal === null ? "" : terminalDiffCard(terminal, run.id, editor, commentForm !== null),
|
|
2244
|
-
reviewCard,
|
|
2245
|
-
]
|
|
2246
|
-
: [resultPanel, editorToggleForm]),
|
|
2247
|
-
running ? "" : facts,
|
|
2248
|
-
evidence,
|
|
2249
|
-
notesCard,
|
|
2250
|
-
], "\n"), {
|
|
2251
|
-
chrome,
|
|
2252
|
-
// One composed functional script (arc 4 contract): the pollers when the
|
|
2253
|
-
// run is live, the result panel's tabs/draft script or the legacy
|
|
2254
|
-
// comment prefill when a form exists. Neither fetches — they earn
|
|
2255
|
-
// neither connect-src nor the noscript refresh.
|
|
2256
|
-
...(liveScript === undefined && commentForm === null && resultPanel === null
|
|
2257
|
-
? {}
|
|
2258
|
-
: {
|
|
2259
|
-
functional: {
|
|
2260
|
-
script: (liveScript ?? "") + (resultPanel !== null ? RESULT_REVIEW_SCRIPT : commentForm === null ? "" : prefillScript()),
|
|
2261
|
-
fetches: liveScript !== undefined,
|
|
2262
|
-
},
|
|
2263
|
-
}),
|
|
2264
|
-
});
|
|
2265
|
-
}
|
|
2266
2129
|
/**
|
|
2267
2130
|
* Click-to-prefill (arc 6, finding 4): client-side FORM mutation, named as
|
|
2268
2131
|
* such — normal viewing stays the default; "Annotate" reveals line pins.
|
|
@@ -2302,10 +2165,10 @@ export function reviewEvidenceScript() {
|
|
|
2302
2165
|
* finding 15). */
|
|
2303
2166
|
export function runFactsFragment(run, taskId, live, route = null) {
|
|
2304
2167
|
if (run.outcome !== null) {
|
|
2305
|
-
return html `<p class="
|
|
2168
|
+
return html `<p class="k-note" data-region-stop>It finished. <a class="k-link" href="/r/${run.id}">Reload for the final record</a></p>`;
|
|
2306
2169
|
}
|
|
2307
2170
|
if (!live) {
|
|
2308
|
-
return html `<p class="
|
|
2171
|
+
return html `<p class="k-note" data-region-stop>It stopped without finishing. <a class="k-link" href="/r/${run.id}">Reload for the record</a></p>`;
|
|
2309
2172
|
}
|
|
2310
2173
|
return runFactsRows(run, taskId, live, route);
|
|
2311
2174
|
}
|
|
@@ -1,14 +1,10 @@
|
|
|
1
|
-
import { type BrandIconId } from "../brand-icons.js";
|
|
2
|
-
import { type BrowserPhoneCard, type BrowserSettingsGroup, type BrowserSettingsView, type BrowserUpdates } from "../browser-workspace.js";
|
|
3
1
|
import { type Gap } from "../gaps.js";
|
|
4
2
|
import { type LeadIdentity } from "../lead-identity.js";
|
|
5
|
-
import { type
|
|
6
|
-
import { type QualityMode } from "../quality.js";
|
|
7
|
-
import { type UnattendedPermissionMode } from "../scope.js";
|
|
8
|
-
import { type Capability, type PushSubscription, type ResultScreenshots, type Store } from "../store.js";
|
|
3
|
+
import { type Capability, type Store } from "../store.js";
|
|
9
4
|
import { type TokenSource } from "../telegram.js";
|
|
10
5
|
import { type Chrome, type Screen } from "./chrome.js";
|
|
11
6
|
import { type Html } from "../html.js";
|
|
7
|
+
import { type WorkerFacts } from "../settings-groups-ui.js";
|
|
12
8
|
/** What the lead's settings form shows beside the saved configuration: where keys come from (never the keys), the
|
|
13
9
|
* live model lists, and where saving goes back to. */
|
|
14
10
|
export type LeadFormFacts = {
|
|
@@ -34,6 +30,7 @@ export declare function leadSettingsHtml(data: {
|
|
|
34
30
|
signedIn: string | null;
|
|
35
31
|
command: string;
|
|
36
32
|
said: string | null;
|
|
33
|
+
problem?: string | null;
|
|
37
34
|
saved?: boolean;
|
|
38
35
|
identity?: LeadIdentity;
|
|
39
36
|
about?: string[];
|
|
@@ -52,7 +49,7 @@ export declare function leadSettingsHtml(data: {
|
|
|
52
49
|
paused: boolean;
|
|
53
50
|
}[];
|
|
54
51
|
}): Html;
|
|
55
|
-
/** The lead's full settings (Settings → Lead → Advanced): provider, model, limits and
|
|
52
|
+
/** The lead's full settings (Settings → Lead → Advanced): provider, model, limits and the lead's own key. */
|
|
56
53
|
export declare function leadConfigForm(current: import("../store.js").ChatConfig | null, data: LeadFormFacts): Html;
|
|
57
54
|
export declare function capsPage(chrome: Chrome, caps: Capability[] | null, gaps: Gap[], repo: string, now?: Date): Screen;
|
|
58
55
|
/** Whether the bot's saved delivery state reports a problem (no new check runs). */
|
|
@@ -65,55 +62,8 @@ export declare function notificationProjects(store: Store, account: string): {
|
|
|
65
62
|
name: string;
|
|
66
63
|
muted: boolean;
|
|
67
64
|
}[];
|
|
68
|
-
export declare function settingsPage(chrome: Chrome, existing: TokenSource | null, hasEnv: boolean, csrf: string, problem: string | null, messaging?: {
|
|
69
|
-
channel: string | null;
|
|
70
|
-
implicit: boolean;
|
|
71
|
-
configured: string[];
|
|
72
|
-
legacyWarning?: string;
|
|
73
|
-
} | null, push?: {
|
|
74
|
-
available: boolean;
|
|
75
|
-
devices: PushSubscription[];
|
|
76
|
-
} | null, providerKeys?: {
|
|
77
|
-
provider: string;
|
|
78
|
-
envName: string;
|
|
79
|
-
set: boolean;
|
|
80
|
-
updatedAt: string | null;
|
|
81
|
-
ambient: boolean;
|
|
82
|
-
mode: "subscription" | "api-key";
|
|
83
|
-
subscriptionCapable: boolean;
|
|
84
|
-
connection?: ProviderConnection;
|
|
85
|
-
}[] | null, digest?: {
|
|
86
|
-
everyMs: number | null;
|
|
87
|
-
lastSentAt: string | null;
|
|
88
|
-
held: number;
|
|
89
|
-
} | null, permissionDefault?: {
|
|
90
|
-
mode: UnattendedPermissionMode;
|
|
91
|
-
updatedAt: string | null;
|
|
92
|
-
updatedBy: string | null;
|
|
93
|
-
canManage: boolean;
|
|
94
|
-
} | null, qualityDefault?: {
|
|
95
|
-
mode: QualityMode;
|
|
96
|
-
updatedAt: string | null;
|
|
97
|
-
updatedBy: string | null;
|
|
98
|
-
canManage: boolean;
|
|
99
|
-
} | null, email?: NonNullable<BrowserSettingsView["email"]> | null, telegramDelivery?: string | null, workers?: NonNullable<BrowserSettingsView["workers"]> | null, updates?: BrowserUpdates | null, firstResult?: string | null, chatNotices?: {
|
|
100
|
-
mode: "quiet" | "all";
|
|
101
|
-
digestAt: string | null;
|
|
102
|
-
screenshots?: ResultScreenshots;
|
|
103
|
-
projects?: {
|
|
104
|
-
repo: string;
|
|
105
|
-
name: string;
|
|
106
|
-
muted: boolean;
|
|
107
|
-
}[];
|
|
108
|
-
} | null, telegramFailing?: boolean, phone?: BrowserPhoneCard | null): Screen;
|
|
109
|
-
/** The phone setup for the server-rendered Settings page: the same choices as the React card. */
|
|
110
|
-
export declare function phoneSetupHtml(phone: BrowserPhoneCard): Html;
|
|
111
65
|
/** Every worker that is not retired: its capacity, and the tasks it holds now. */
|
|
112
|
-
export declare function settingsWorkers(store: Store, now: Date):
|
|
113
|
-
/** The page's workers section, for browsers without the app script. */
|
|
114
|
-
export declare function workersCard(workers: NonNullable<BrowserSettingsView["workers"]> | null): Html;
|
|
115
|
-
/** Settings → Updates, for browsers without the app script. */
|
|
116
|
-
export declare function updatesCard(updates: BrowserUpdates | null): Html;
|
|
66
|
+
export declare function settingsWorkers(store: Store, now: Date): WorkerFacts[];
|
|
117
67
|
/** Choices save the moment they change; without the script the Save
|
|
118
68
|
* button stays and the form works the same. */
|
|
119
69
|
export declare const SETTINGS_AUTOSAVE_SCRIPT = "(function(){document.querySelectorAll('form[data-autosave]').forEach(function(form){form.classList.add('js-autosave');form.addEventListener('change',function(ev){var t=ev.target;if(t&&(t.type==='radio'||t.tagName==='SELECT')){if(form.requestSubmit)form.requestSubmit();else form.submit();}});});})();";
|
|
@@ -133,22 +83,3 @@ export declare function latestReleaseFor(latest: (() => Promise<{
|
|
|
133
83
|
} | {
|
|
134
84
|
problem: string;
|
|
135
85
|
}>;
|
|
136
|
-
/** Settings destinations under short headings: an icon and a name each, and a chat app's logo and state. */
|
|
137
|
-
export declare function settingsTiles(groups: BrowserSettingsGroup[]): Html;
|
|
138
|
-
/** Each destination once, in order: a group's heading, then its [href, label, icon] tiles. */
|
|
139
|
-
export declare const SETTINGS_GROUPS: [string, [string, string, Html][]][];
|
|
140
|
-
export declare const SETTINGS_TILE_ICONS: Map<string, Html>;
|
|
141
|
-
export declare const CHAT_APP_TILES: Record<string, BrandIconId>;
|
|
142
|
-
/**
|
|
143
|
-
* The settings groups, with each chat app's state from what the server already holds: not set up,
|
|
144
|
-
* connected, or getting alerts (only when that service was chosen, or is the only one).
|
|
145
|
-
* A Telegram bot whose saved delivery state reports a problem says so instead. With no config folder
|
|
146
|
-
* the state is unknown, so the tiles carry none.
|
|
147
|
-
*/
|
|
148
|
-
export declare function settingsGroups(messaging: {
|
|
149
|
-
channel: string | null;
|
|
150
|
-
implicit: boolean;
|
|
151
|
-
configured: string[];
|
|
152
|
-
} | null, telegramFailing?: boolean): BrowserSettingsGroup[];
|
|
153
|
-
/** Light, dark or the device's choice, one tap each. Per browser (a cookie). */
|
|
154
|
-
export declare function appearanceCard(csrf: string): Html;
|