toolroll 0.9.51 → 0.9.53
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 +20 -0
- package/README.md +55 -80
- package/dist/agentconfig.d.ts +11 -36
- package/dist/agentconfig.js +3 -62
- package/dist/approval-policy.d.ts +1 -1
- package/dist/approval-policy.js +1 -1
- package/dist/backup.d.ts +8 -0
- package/dist/backup.js +10 -1
- package/dist/board.d.ts +3 -19
- package/dist/board.js +4 -42
- package/dist/browser/workspace.css +1 -1
- package/dist/browser/workspace.js +18 -18
- package/dist/browser-workspace.d.ts +3 -1
- package/dist/builder.d.ts +9 -40
- package/dist/builder.js +50 -257
- package/dist/chat-actions.js +3 -14
- package/dist/chat-controls.d.ts +0 -4
- package/dist/chat-controls.js +0 -1
- package/dist/chat-decide.js +1 -3
- package/dist/chat-delivery.d.ts +0 -2
- package/dist/chat-delivery.js +0 -1
- package/dist/chat-quiet.js +2 -2
- package/dist/chat-task-actions.d.ts +1 -1
- package/dist/chat-task-actions.js +0 -2
- package/dist/claim.d.ts +79 -244
- package/dist/claim.js +688 -1023
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +10 -2
- package/dist/contracts/cli.d.ts +0 -13
- package/dist/contracts/cli.js +0 -2
- package/dist/contracts/console-api.d.ts +5 -10
- package/dist/contracts/console-api.js +4 -10
- package/dist/contracts/flow.d.ts +50 -0
- package/dist/contracts/flow.js +26 -1
- package/dist/contracts/lead-tools.d.ts +0 -13
- package/dist/contracts/lead-tools.js +3 -3
- package/dist/contracts/store-json.d.ts +1 -25
- package/dist/contracts/store-json.js +3 -13
- package/dist/converse.d.ts +1 -11
- package/dist/converse.js +6 -38
- package/dist/coordinator.d.ts +0 -1
- package/dist/coordinator.js +3 -5
- package/dist/database-reclaim.d.ts +4 -0
- package/dist/database-reclaim.js +13 -0
- package/dist/demo.d.ts +1 -1
- package/dist/demo.js +17 -27
- package/dist/desktop-update-gate.js +0 -1
- package/dist/desktop-update.d.ts +1 -1
- package/dist/desktop-update.js +1 -3
- package/dist/dispatch.d.ts +1 -1
- package/dist/dispatch.js +1 -1
- package/dist/dispose.d.ts +2 -3
- package/dist/dispose.js +17 -92
- package/dist/envelope.js +0 -3
- package/dist/exec.d.ts +0 -64
- package/dist/exec.js +3 -356
- package/dist/exhaustion.d.ts +22 -76
- package/dist/exhaustion.js +14 -140
- package/dist/export.js +4 -4
- package/dist/flow-engine.js +1 -1
- package/dist/flow-schedule.d.ts +154 -0
- package/dist/flow-schedule.js +321 -0
- package/dist/flow-share.js +1 -1
- package/dist/flow-triggers.d.ts +6 -1
- package/dist/flow-triggers.js +65 -10
- package/dist/flows-cli.js +8 -4
- package/dist/flows-ui.js +2 -0
- package/dist/flows.js +1 -1
- package/dist/guides.js +9 -29
- package/dist/invoke.d.ts +1 -24
- package/dist/invoke.js +17 -259
- package/dist/lead-status.js +2 -4
- package/dist/lead-voice.js +1 -1
- package/dist/live-bus.d.ts +3 -3
- package/dist/live-bus.js +3 -3
- package/dist/mate-doors.d.ts +1 -2
- package/dist/mate-doors.js +12 -25
- package/dist/mate-tools.d.ts +2 -2
- package/dist/mate-tools.js +10 -22
- package/dist/modes.d.ts +6 -7
- package/dist/modes.js +7 -13
- package/dist/monitoring.js +32 -8
- package/dist/notification-delivery.d.ts +19 -0
- package/dist/notification-delivery.js +37 -0
- package/dist/operate-remote-arguments.js +2 -6
- package/dist/operate-remote.js +6 -7
- package/dist/operate.d.ts +0 -6
- package/dist/operate.js +283 -2378
- package/dist/phase-routing.d.ts +13 -23
- package/dist/phase-routing.js +13 -35
- package/dist/plan-auto.js +2 -2
- package/dist/planner-source.js +2 -1
- package/dist/policy.d.ts +1 -4
- package/dist/policy.js +0 -8
- package/dist/process-recovery-eligibility.js +2 -3
- package/dist/process-recovery-settlement.js +1 -0
- package/dist/project-delete.js +3 -15
- package/dist/proposal.d.ts +4 -24
- package/dist/proposal.js +3 -88
- package/dist/provider-auth.d.ts +3 -3
- package/dist/provider-auth.js +4 -6
- package/dist/provider.d.ts +11 -25
- package/dist/provider.js +4 -36
- package/dist/push.js +1 -1
- package/dist/recipe-ui.js +6 -6
- package/dist/recipes.d.ts +3 -3
- package/dist/recipes.js +27 -23
- package/dist/retention.js +6 -5
- package/dist/run-closeout.d.ts +1 -1
- package/dist/run-closeout.js +1 -4
- package/dist/scope.d.ts +11 -65
- package/dist/scope.js +17 -82
- package/dist/serve.js +16 -25
- package/dist/server/chat.js +7 -30
- package/dist/server/flows.js +11 -10
- package/dist/server/guards.js +0 -1
- package/dist/server/pages-assets.js +1 -1
- package/dist/server/pages.js +0 -2
- package/dist/server/people-tokens.js +0 -4
- package/dist/server/route-table.d.ts +1 -1
- package/dist/server/route-table.js +2 -17
- package/dist/server/settings.js +4 -9
- package/dist/server/shared.d.ts +29 -212
- package/dist/server/shared.js +73 -780
- package/dist/server/task-views.js +9 -76
- package/dist/server/tasks.d.ts +1 -50
- package/dist/server/tasks.js +36 -946
- package/dist/setup-guide.d.ts +2 -2
- package/dist/slack-chat.d.ts +0 -2
- package/dist/slack-chat.js +0 -1
- package/dist/store.d.ts +142 -1382
- package/dist/store.js +900 -4083
- package/dist/surface.js +10 -25
- package/dist/task-composer.d.ts +1 -1
- package/dist/task-composer.js +1 -1
- package/dist/task-control.d.ts +3 -10
- package/dist/task-control.js +2 -7
- package/dist/teammate-desk.js +1 -1
- package/dist/teammates-ui.js +1 -1
- package/dist/telegram-mate.d.ts +0 -3
- package/dist/telegram-mate.js +0 -1
- package/dist/templates.d.ts +11 -7
- package/dist/templates.js +12 -9
- package/dist/toolroll-update.d.ts +24 -3
- package/dist/toolroll-update.js +159 -16
- package/dist/webhooks.d.ts +10 -22
- package/dist/webhooks.js +43 -81
- package/dist/work-index.js +3 -7
- package/dist/workspace-revision.d.ts +28 -1
- package/dist/workspace-revision.js +276 -49
- package/dist/workspace-ui.js +1 -1
- package/package.json +1 -3
- package/scripts/recovery-canary.mjs +3 -3
- package/dist/contest.d.ts +0 -318
- package/dist/contest.js +0 -753
- package/dist/held.d.ts +0 -150
- package/dist/held.js +0 -799
- package/dist/liveness.d.ts +0 -30
- package/dist/liveness.js +0 -42
- package/dist/pricing.d.ts +0 -45
- package/dist/pricing.js +0 -77
- package/dist/routine.d.ts +0 -228
- package/dist/routine.js +0 -764
- package/dist/supervisor.mjs +0 -297
|
@@ -36,7 +36,7 @@ const PWA_MANIFEST = JSON.stringify({
|
|
|
36
36
|
// paths — the payload URL is data, revalidated, never handed raw to the
|
|
37
37
|
// browser (arc 3 finding 5).
|
|
38
38
|
const PWA_WORKER = `// Toolroll — push only; deliberately NO fetch handler (no offline cache of an authenticated console).
|
|
39
|
-
const SHAPES = [/^\\/next$/, /^\\/review$/, /^\\/system$/, /^\\/routines$/, /^\\/routines\\/[0-9]+$/, /^\\/d\\/[0-9]+$/, /^\\/
|
|
39
|
+
const SHAPES = [/^\\/next$/, /^\\/review$/, /^\\/system$/, /^\\/routines$/, /^\\/routines\\/[0-9]+$/, /^\\/d\\/[0-9]+$/, /^\\/r\\/[0-9]+$/];
|
|
40
40
|
self.addEventListener("push", function (event) {
|
|
41
41
|
var data = {};
|
|
42
42
|
try { data = event.data ? event.data.json() : {}; } catch (e) {}
|
package/dist/server/pages.js
CHANGED
|
@@ -320,7 +320,6 @@ export function createPagesHandlers(runtime) {
|
|
|
320
320
|
settings: options.telegramTokenFile !== undefined,
|
|
321
321
|
building: store.liveClaims(project, now),
|
|
322
322
|
runners: store.listRunners(),
|
|
323
|
-
heldSessions: new Map(store.openHeldSessions().reduce((by, one) => by.set(one.runner, (by.get(one.runner) ?? 0) + 1), new Map())),
|
|
324
323
|
worktrees: store
|
|
325
324
|
.listWorktrees()
|
|
326
325
|
.filter(one => project === null || sameRepo(one.repo, project)),
|
|
@@ -346,7 +345,6 @@ export function createPagesHandlers(runtime) {
|
|
|
346
345
|
}),
|
|
347
346
|
building: store.liveClaims(project, now),
|
|
348
347
|
runners: store.listRunners(),
|
|
349
|
-
heldSessions: new Map(store.openHeldSessions().reduce((by, one) => by.set(one.runner, (by.get(one.runner) ?? 0) + 1), new Map())),
|
|
350
348
|
worktrees: store.listWorktrees().filter(one => project === null || sameRepo(one.repo, project)),
|
|
351
349
|
episode: project === null ? null : store.latestWatchEpisode(project),
|
|
352
350
|
outboxPending: store.pendingForAttention().length,
|
|
@@ -73,7 +73,6 @@ export function createPeopleHandlers(runtime) {
|
|
|
73
73
|
`<p class="meta">Operators with all-project access also manage the instance.</p><fieldset><legend>Projects</legend>${projectChoices.length === 0 ? `<p class="meta">Add a project before granting selected access.</p>` : projectChoices.map(repo => `<label class="row"><input type="checkbox" name="projects" value="${escape(repo)}"${selected?.includes(repo) ? " checked" : ""}>${escape(projectName(repo))}</label>`).join("")}</fieldset>`;
|
|
74
74
|
const cards = accounts.map(one => {
|
|
75
75
|
const seen = lastSeenOf(one.name);
|
|
76
|
-
const attended = store.openAttendedOf(one.name);
|
|
77
76
|
const acts = store.recentActsOf(one.name);
|
|
78
77
|
const standing = one.revokedAt !== null
|
|
79
78
|
? `revoked ${escape(one.revokedAt.slice(0, 16).replace("T", " "))} by ${personChip(one.revokedBy ?? "?")}`
|
|
@@ -87,9 +86,6 @@ export function createPeopleHandlers(runtime) {
|
|
|
87
86
|
approverView && one.revokedAt === null ? `<details><summary>Edit project access</summary><form method="post" action="/people/projects">${hiddenFields({ csrf, name: one.name })}${accessFields(one.projects)}<label>Your password<input type="password" name="token" autocomplete="current-password" required></label><p class="meta">Changing access signs this person out and ends their derived sessions and modes. Previously approved work stays recorded.</p><button type="submit">Save project access</button></form></details>` : "",
|
|
88
87
|
`<p class="meta">${seen === null ? "not signed in right now" : `signed in \u2014 active ${escape(new Date(seen).toISOString().slice(11, 16))} UTC`} \u00b7 joined ${escape(one.addedAt.slice(0, 10))}</p>`,
|
|
89
88
|
`<p><a href="${escape(personHref(one.name))}">Tokens and remote activity</a></p>`,
|
|
90
|
-
attended.length === 0
|
|
91
|
-
? ""
|
|
92
|
-
: `<p class="row">watching now: ${attended.map(session => `<a href="/t/${escape(session.taskId)}">${escape(session.taskId)}</a>`).join(", ")}</p>`,
|
|
93
89
|
acts.length === 0
|
|
94
90
|
? `<p class="meta">No recorded acts yet</p>`
|
|
95
91
|
: acts.map(act => `<p class="row meta">${escape(act.kind)} ${escape(act.subject)} \u00b7 ${escape(act.at.slice(0, 16).replace("T", " "))}</p>`).join("\n"),
|
|
@@ -17,7 +17,7 @@ export type Caller = "anonymous" | "service" | "cookie" | "bearer" | "oauth" | "
|
|
|
17
17
|
/** What the caller must hold: nothing, read, act (an approver or an `act` token), or a fresh password/provider check on top. */
|
|
18
18
|
export type RouteScope = "none" | "read" | "act" | "step-up";
|
|
19
19
|
/** Where the request's project comes from. */
|
|
20
|
-
export type ProjectResolver = "none" | "session" | "form" | "form-path" | "task" | "run" | "decision" | "incident" | "
|
|
20
|
+
export type ProjectResolver = "none" | "session" | "form" | "form-path" | "task" | "run" | "decision" | "incident" | "flow" | "proposal" | "conversation" | "coding" | "adapter";
|
|
21
21
|
/**
|
|
22
22
|
* What a project-limited account may do here:
|
|
23
23
|
* - `deny`: instance access only.
|
|
@@ -120,7 +120,6 @@ get("tasks", "runs", "/runs", { limited: "collection" });
|
|
|
120
120
|
get("pages", "menu", "/menu", { limited: "collection", ...free });
|
|
121
121
|
get("tasks", "run.page", `^\\/r\\/${ID}$`, { project: "run", limited: "resource", ...free, sample: "/r/1" });
|
|
122
122
|
get("tasks", "run.evidence", `^\\/r\\/${ID}\\/evidence\\/${ID}$`, { project: "run", limited: "resource", ...free, sample: "/r/1/evidence/2" });
|
|
123
|
-
get("tasks", "contest.page", `^\\/contest\\/${ID}$`, { ...free, sample: "/contest/1" });
|
|
124
123
|
get("pages", "caps", "/caps");
|
|
125
124
|
get("flows", "flows.new", "/flows/new", { limited: "resource", ...free });
|
|
126
125
|
get("flows", "flows.gallery", "^\\/flows\\/new\\/[a-z-]{1,40}$", { limited: "resource", ...free, sample: "/flows/new/triage" });
|
|
@@ -139,13 +138,14 @@ for (const one of ["run", "start", "new", "edit", "from-task", "preview", "expor
|
|
|
139
138
|
get("flows", `recipes.${one}`, `/recipes/${one}`, { limited: "collection" });
|
|
140
139
|
// Any other recipe screen answers the recipe area's own refusal.
|
|
141
140
|
get("flows", "recipes.other", "^\\/recipes\\/.*$", { sample: "/recipes/unknown" });
|
|
141
|
+
// v115: routines became scheduled flows; old links to them land on the flows page.
|
|
142
142
|
get("tasks", "routines", "/routines", { limited: "collection" });
|
|
143
143
|
get("chat", "chat.stream", "/chat/stream", free);
|
|
144
144
|
get("chat", "chat.mate-status", "/chat/mate/status", free);
|
|
145
145
|
get("chat", "chat.demo-live", "/chat/demo/live", free);
|
|
146
146
|
get("chat", "chat.page", "/chat", { project: "conversation", limited: "conversation", ...free });
|
|
147
147
|
get("chat", "chat.ack", `^\\/chat\\/ack\\/${ID}$`, { sample: "/chat/ack/1" });
|
|
148
|
-
get("tasks", "routine.page", `^\\/routines\\/${ID}$`, {
|
|
148
|
+
get("tasks", "routine.page", `^\\/routines\\/${ID}$`, { limited: "resource", sample: "/routines/1" });
|
|
149
149
|
get("settings", "control", "/control");
|
|
150
150
|
get("settings", "control.connection", "/control/connection");
|
|
151
151
|
get("chat", "chat.action", `^\\/chat\\/action\\/${ID}$`, { project: "proposal", limited: "proposal", ...free, sample: "/chat/action/1" });
|
|
@@ -166,8 +166,6 @@ get("chat", "lead.status", "/lead/status", free);
|
|
|
166
166
|
get("chat", "chat.task-status", "/chat/task-status", free);
|
|
167
167
|
get("tasks", "decision.evidence", `^\\/d\\/${ID}\\/evidence\\/${ID}$`, { project: "decision", limited: "resource", ...free, sample: "/d/1/evidence/2" });
|
|
168
168
|
// ---- console actions -------------------------------------------------------------------------------------------
|
|
169
|
-
// The attended beat guards itself (cookie, form type, Sec-Fetch-Site) before the shared mutation guard.
|
|
170
|
-
post("tasks", "session.attended-beats", "/session/attended-beats", { callers: ["cookie"], scopeRefusal: "your login can watch, not keep sessions alive", callerRefusal: { status: 403, type: "text/plain; charset=utf-8", body: "watching is a browser session's act" } });
|
|
171
169
|
// The scripted demo: the handler answers a non-browser caller "no page here".
|
|
172
170
|
post("chat", "chat.demo", "^\\/chat\\/demo\\/(ask|[0-9]{1,9}\\/(approve|change|revise|complete))$", { sample: "/chat/demo/ask" });
|
|
173
171
|
post("settings", "provider.resume", "^\\/providers\\/[a-z]+\\/resume$", { sample: "/providers/codex/resume" });
|
|
@@ -243,12 +241,6 @@ post("people", "people.revoke", "/people/revoke", { scope: "step-up" });
|
|
|
243
241
|
post("pages", "fleet.retire", "/fleet/runner/retire", { scope: "step-up" });
|
|
244
242
|
// Answering a parked decision needs act access and irreversible-choice confirmation, not password step-up.
|
|
245
243
|
post("tasks", "decision.answer", `^\\/d\\/${ID}\\/answer$`, { project: "decision", limited: "resource", scope: "act", sample: "/d/1/answer" });
|
|
246
|
-
post("tasks", "contest.act.arm", `^\\/contest\\/${ID}\\/arm$`, { sample: "/contest/1/arm" });
|
|
247
|
-
post("tasks", "contest.act.pick", `^\\/contest\\/${ID}\\/pick$`, { scope: "step-up", sample: "/contest/1/pick" });
|
|
248
|
-
post("tasks", "contest.act.abandon", `^\\/contest\\/${ID}\\/abandon$`, { scope: "step-up", sample: "/contest/1/abandon" });
|
|
249
|
-
post("tasks", "task.attend.attend-preview", `^\\/t\\/${TASK}\\/attend-preview$`, { callers: ["cookie"], project: "task", sample: "/t/one/attend-preview" });
|
|
250
|
-
post("tasks", "task.attend.attend", `^\\/t\\/${TASK}\\/attend$`, { scope: "step-up", project: "task", sample: "/t/one/attend" });
|
|
251
|
-
post("tasks", "task.attend.attend-revoke", `^\\/t\\/${TASK}\\/attend-revoke$`, { callers: ["cookie"], project: "task", sample: "/t/one/attend-revoke" });
|
|
252
244
|
post("tasks", "task.act.hold", `^\\/t\\/${TASK}\\/hold$`, { project: "task", limited: "resource", sample: "/t/one/hold" });
|
|
253
245
|
post("tasks", "task.act.unhold", `^\\/t\\/${TASK}\\/unhold$`, { project: "task", limited: "resource", sample: "/t/one/unhold" });
|
|
254
246
|
post("tasks", "task.act.requeue", `^\\/t\\/${TASK}\\/requeue$`, { project: "task", limited: "resource", sample: "/t/one/requeue" });
|
|
@@ -291,15 +283,8 @@ post("chat", "chat.ack-send", `^\\/chat\\/ack\\/${ID}$`, { scope: "step-up", sam
|
|
|
291
283
|
for (const one of ["prepare", "preview", "import", "save"])
|
|
292
284
|
post("flows", `recipes.${one}-send`, `/recipes/${one}`, { limited: "collection" });
|
|
293
285
|
post("flows", "recipes.launch-send", "/recipes/launch", { limited: "collection" });
|
|
294
|
-
post("tasks", "routines.add", "/routines/add", { project: "form", limited: "collection" });
|
|
295
|
-
post("tasks", "routine.act.approve", `^\\/routines\\/${ID}\\/approve$`, { scope: "step-up", project: "routine", limited: "resource", sample: "/routines/1/approve" });
|
|
296
|
-
post("tasks", "routine.act.refresh", `^\\/routines\\/${ID}\\/refresh$`, { project: "routine", limited: "resource", sample: "/routines/1/refresh" });
|
|
297
|
-
post("tasks", "routine.act.pause", `^\\/routines\\/${ID}\\/pause$`, { project: "routine", limited: "resource", sample: "/routines/1/pause" });
|
|
298
|
-
post("tasks", "routine.act.resume", `^\\/routines\\/${ID}\\/resume$`, { project: "routine", limited: "resource", sample: "/routines/1/resume" });
|
|
299
|
-
post("tasks", "routine.act.run-now", `^\\/routines\\/${ID}\\/run-now$`, { scope: "step-up", project: "routine", limited: "resource", sample: "/routines/1/run-now" });
|
|
300
286
|
post("tasks", "run.act", `^\\/r\\/${ID}\\/(note|comment|revise|draft-repair|checks|add-tests)$`, { project: "run", limited: "resource", sample: "/r/1/note" });
|
|
301
287
|
post("tasks", "session.editor-links", "/session/editor-links", { viewer: true });
|
|
302
|
-
post("tasks", "run.turn", `^\\/r\\/${ID}\\/turn$`, { project: "run", sample: "/r/1/turn" });
|
|
303
288
|
post("tasks", "incident.resolve", `^\\/i\\/${ID}\\/resolve$`, { project: "incident", sample: "/i/1/resolve" });
|
|
304
289
|
/** The sole route table, in match order. */
|
|
305
290
|
export const ROUTES = Object.freeze(rows.map(one => Object.freeze(one)));
|
package/dist/server/settings.js
CHANGED
|
@@ -200,10 +200,6 @@ export function createSettingsHandlers(runtime) {
|
|
|
200
200
|
`<option value="">approve plans and merges here, with my password (the default)</option>` +
|
|
201
201
|
`<option value="1">approve plans and merge ready pull requests from my paired chat, two taps each</option>` +
|
|
202
202
|
`</select><span class="meta">Plans that widen permissions, exceed the attempt cap or touch protected paths still open Toolroll.</span></label>`,
|
|
203
|
-
`<label>If a subscription runs out<select name="allow-paid-fallback">` +
|
|
204
|
-
`<option value="">never switch to a paid API key on its own (the default, every preset)</option>` +
|
|
205
|
-
`<option value="1">allow the approved fallback — spend moves to that account</option>` +
|
|
206
|
-
`</select></label>`,
|
|
207
203
|
`<button type="submit">Read the full terms</button>`,
|
|
208
204
|
`</form>`,
|
|
209
205
|
`</div>`,
|
|
@@ -1111,6 +1107,8 @@ export function createSettingsHandlers(runtime) {
|
|
|
1111
1107
|
if (who.via !== "cookie" || !store.isInstanceOperator(who.name) || databaseFile === null)
|
|
1112
1108
|
return refuse(response, who, 403, "An instance operator looks after backups.", "/settings");
|
|
1113
1109
|
const made = await backupNow(store, databaseFile, "manual", clock);
|
|
1110
|
+
if (made.ok && made.checkpoint !== null && "problem" in made.checkpoint)
|
|
1111
|
+
return redirect(response, `/settings/backups?problem=${encodeURIComponent(`Backed up. The activity log failed its tamper check, so it was not anchored: ${made.checkpoint.problem}`)}`);
|
|
1114
1112
|
return redirect(response, made.ok ? `/settings/backups?said=${encodeURIComponent("Backed up.")}` : `/settings/backups?problem=${encodeURIComponent(`The backup failed: ${made.error}`)}`);
|
|
1115
1113
|
}
|
|
1116
1114
|
// Sprint 8: change the backup schedule. A step-up; the ledger keeps before → after.
|
|
@@ -1978,7 +1976,7 @@ export function createSettingsHandlers(runtime) {
|
|
|
1978
1976
|
const existing = loadBotToken({}, options.telegramTokenFile);
|
|
1979
1977
|
const hasEnv = (envValue(process.env, "TELEGRAM_TOKEN") ?? "") !== "";
|
|
1980
1978
|
const csrf = who.via === "cookie" ? who.session.csrf : "";
|
|
1981
|
-
return sendScreen(response, 400, settingsPage(chromeFor(who.via === "cookie" ? who.session.project : defaultProject, "settings"), existing, hasEnv, csrf, saved.message, null, null, null, null, {
|
|
1979
|
+
return sendScreen(response, 400, settingsPage(chromeFor(who.via === "cookie" ? who.session.project : defaultProject, "settings"), existing, hasEnv, csrf, saved.message, options.configDir === undefined ? null : effectivePrimary(process.env, options.configDir, loadBotToken(process.env, options.telegramTokenFile) !== null), null, null, null, {
|
|
1982
1980
|
...store.permissionDefault(),
|
|
1983
1981
|
canManage: who.role === "approver",
|
|
1984
1982
|
}));
|
|
@@ -2047,9 +2045,6 @@ export function createSettingsHandlers(runtime) {
|
|
|
2047
2045
|
planAuto: body.get("plan-auto") === "1",
|
|
2048
2046
|
reviewAuto: false,
|
|
2049
2047
|
reviewRetryAuto: false,
|
|
2050
|
-
// The paid-fallback grant is NEVER a preset default (R8): unchecked
|
|
2051
|
-
// stays false on every preset — only the explicit box grants it.
|
|
2052
|
-
allowPaidFallback: body.get("allow-paid-fallback") === "1",
|
|
2053
2048
|
// The repair-auto grant is the SAME rule (v40): unchecked stays
|
|
2054
2049
|
// false on every preset — only the explicit box grants it, and the
|
|
2055
2050
|
// attempt cap it carries is meaningless without it.
|
|
@@ -2078,7 +2073,7 @@ export function createSettingsHandlers(runtime) {
|
|
|
2078
2073
|
`<input type="hidden" name="csrf" value="${escape(who.session.csrf)}">` +
|
|
2079
2074
|
`<input type="hidden" name="nonce" value="${escape(nonce)}">` +
|
|
2080
2075
|
`<input type="hidden" name="digest" value="${escape(digest)}">` +
|
|
2081
|
-
["name", "days", "publication", "auto-approve", "plan-auto", "chat-approve"
|
|
2076
|
+
["name", "days", "publication", "auto-approve", "plan-auto", "chat-approve"]
|
|
2082
2077
|
.map(field => `<input type="hidden" name="${field}" value="${escape(body.get(field) ?? "")}">`)
|
|
2083
2078
|
.join("") +
|
|
2084
2079
|
`<input type="hidden" name="expiry" value="${escape(expiry)}">` +
|