toolroll 0.9.55 → 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 +10 -0
- package/README.md +24 -8
- package/dist/action-ledger.d.ts +2 -4
- package/dist/action-ledger.js +2 -10
- package/dist/approval-policy.d.ts +5 -5
- package/dist/approval-policy.js +4 -4
- package/dist/approval-rules-ui.js +2 -2
- package/dist/browser/workspace.js +5 -5
- package/dist/browser-workspace.d.ts +12 -12
- 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-rooms.js +3 -3
- package/dist/chat-warmth.d.ts +2 -2
- package/dist/cli.d.ts +1 -1
- package/dist/cli.js +6 -7
- 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/console-api.d.ts +6 -6
- package/dist/contracts/console-api.js +7 -7
- 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/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/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/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/dispatch.d.ts +1 -1
- package/dist/dispatch.js +1 -1
- package/dist/envelope.js +0 -1
- package/dist/export-ui.js +1 -1
- package/dist/export.js +7 -7
- package/dist/flow-engine.d.ts +2 -2
- package/dist/flow-engine.js +21 -21
- package/dist/flow-insights.d.ts +1 -1
- package/dist/flow-share.js +13 -8
- package/dist/flow-steps.d.ts +5 -5
- package/dist/flow-steps.js +19 -19
- package/dist/flow-triggers.d.ts +1 -1
- package/dist/flow-triggers.js +1 -1
- package/dist/flows-cli.js +1 -1
- package/dist/flows-ui.js +20 -20
- package/dist/flows.js +19 -19
- package/dist/guides.js +4 -3
- package/dist/invoke.js +1 -1
- package/dist/kits-ui.js +5 -5
- package/dist/kits.d.ts +12 -12
- package/dist/kits.js +31 -31
- 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 +2 -2
- package/dist/lead-context.js +9 -9
- 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/limits-ui.d.ts +1 -1
- package/dist/limits-ui.js +1 -1
- package/dist/mcp-connect.d.ts +1 -1
- package/dist/mcp-connect.js +3 -3
- package/dist/mcp-core.js +1 -1
- package/dist/memory-pass.d.ts +2 -2
- package/dist/memory-pass.js +7 -7
- package/dist/notification-rows.d.ts +2 -2
- package/dist/operate.d.ts +3 -3
- package/dist/operate.js +35 -34
- 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.js +1 -1
- 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/recipe-ui.js +1 -1
- 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.js +40 -45
- package/dist/server/chat.d.ts +4 -4
- package/dist/server/chat.js +97 -97
- package/dist/server/chrome.js +3 -3
- package/dist/server/flows.js +69 -62
- package/dist/server/guards.js +3 -3
- package/dist/server/http.d.ts +3 -3
- package/dist/server/http.js +1 -1
- package/dist/server/live.js +6 -6
- package/dist/server/people-tokens.js +1 -1
- package/dist/server/remote.js +12 -10
- package/dist/server/render-chat.d.ts +30 -30
- package/dist/server/render-chat.js +33 -33
- package/dist/server/render-pages.js +2 -2
- package/dist/server/render-settings.d.ts +7 -0
- package/dist/server/render-settings.js +3 -0
- package/dist/server/route-table.js +9 -7
- package/dist/server/runtime.d.ts +13 -13
- package/dist/server/settings.js +14 -13
- package/dist/server/tasks.js +6 -5
- package/dist/setup-guide.d.ts +2 -2
- package/dist/slack-chat.d.ts +2 -2
- package/dist/slack-chat.js +6 -6
- package/dist/spend-ui.d.ts +3 -3
- package/dist/spend-ui.js +9 -9
- package/dist/spend.d.ts +14 -14
- package/dist/spend.js +31 -31
- 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/{teammates-ui.js → subagents-ui.js} +45 -45
- 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 +7 -31
- package/dist/team-cli.d.ts +1 -0
- package/dist/team-cli.js +14 -2
- package/dist/team-leads.js +13 -13
- package/dist/team-runtime.d.ts +2 -2
- package/dist/team-runtime.js +8 -8
- package/dist/teams-chat.js +6 -6
- 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-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.d.ts +8 -0
- package/dist/toolroll-update.js +45 -8
- package/package.json +1 -2
- package/dist/teammate-admin.d.ts +0 -53
- package/dist/teammates-ui.d.ts +0 -21
package/dist/server/flows.js
CHANGED
|
@@ -29,13 +29,13 @@ import { authorizedProject, projectName, rowVisible } from "../project.js";
|
|
|
29
29
|
import { recipeAnswersFromForm, recipeDefinitionPreviewHtml, recipeEditorHtml, recipeFromForm, recipeLibraryHtml, recipeRunHtml, recipeScript, workflowPreviewHtml } from "../recipe-ui.js";
|
|
30
30
|
import { createWorkflowPreview, exportRecipe, findRecipe, importRecipe, launchWorkflow, prepareRecipeRun, RecipeError, savedRecipes, saveWorkflowRecipe, starterRecipes, workflowPreview } from "../recipes.js";
|
|
31
31
|
import { isAlive as runnerAlive } from "../runner.js";
|
|
32
|
-
import {
|
|
33
|
-
import { addRoutine, removeRoutine, runRoutine } from "../
|
|
34
|
-
import { editMemory, forgetMemory,
|
|
35
|
-
import { grantTool, revokeTool, rulesFromForm, setToolRules } from "../
|
|
36
|
-
import {
|
|
37
|
-
import {
|
|
38
|
-
import { BLANK_SOUL,
|
|
32
|
+
import { createSubagentFrom, labelOf, nameOf, saveSoul, sendSubagentSummaries, setSubagentState, subagentSettings } from "../subagent-admin.js";
|
|
33
|
+
import { addRoutine, removeRoutine, runRoutine } from "../subagent-desk.js";
|
|
34
|
+
import { editMemory, forgetMemory, tellSubagent } from "../subagent-memory.js";
|
|
35
|
+
import { grantTool, revokeTool, rulesFromForm, setToolRules } from "../subagent-tools.js";
|
|
36
|
+
import { sendSubagentWeeklies, undoCall } from "../subagent-week.js";
|
|
37
|
+
import { answerSubagentQuestion } from "../subagent-work.js";
|
|
38
|
+
import { BLANK_SOUL, subagentPageHtml, subagentsListHtml } from "../subagents-ui.js";
|
|
39
39
|
import { requestContext } from "./request-context.js";
|
|
40
40
|
import { refuse, screen } from "./chrome.js";
|
|
41
41
|
import { redirect, respond, SAFETY, taskHref } from "./http.js";
|
|
@@ -67,9 +67,9 @@ export function createFlowsHandlers(runtime) {
|
|
|
67
67
|
const flow = store.getFlow(id);
|
|
68
68
|
return flow === null || flow.state !== "active" || !visible(flow.repo) ? null : flow;
|
|
69
69
|
};
|
|
70
|
-
/** A
|
|
71
|
-
const
|
|
72
|
-
const mate = store.
|
|
70
|
+
/** A subagent the caller may see: not removed, in a visible project the account can access. */
|
|
71
|
+
const visibleSubagent = (who, id) => {
|
|
72
|
+
const mate = store.getSubagent(id);
|
|
73
73
|
return mate === null || mate.state === "removed" || !visible(mate.repo) || !store.accountCanAccess(who.name, mate.repo) ? null : mate;
|
|
74
74
|
};
|
|
75
75
|
const sendJson = (response, status, payload) => respond(response, status, "application/json; charset=utf-8", JSON.stringify(payload));
|
|
@@ -170,25 +170,31 @@ export function createFlowsHandlers(runtime) {
|
|
|
170
170
|
return redirect(response, "/kits");
|
|
171
171
|
return sendScreen(response, 200, screen(kit.name, html `<h1>${kit.name}</h1>${(kitPageHtml(store, kit, repo, options.configDir ?? null, canSetUp, { said: url.searchParams.get("said"), problem: url.searchParams.get("problem") }))}`, { chrome: chromeFor(repo, "flows") }));
|
|
172
172
|
}
|
|
173
|
-
// ---- v92:
|
|
174
|
-
async function
|
|
173
|
+
// ---- v92 / D5: the lead's subagents — the list, and one page per subagent ----
|
|
174
|
+
async function subagentsPage(ctx) {
|
|
175
175
|
const { url, who, response, project } = ctx;
|
|
176
176
|
const projects = consoleProjects();
|
|
177
|
-
return sendScreen(response, 200, screen("
|
|
177
|
+
return sendScreen(response, 200, screen("Subagents", html `<p><a href="/settings/lead">Lead</a></p><h1>Subagents</h1>${(subagentsListHtml(store, store.subagents(projects), projects, projectName, who.via === "cookie" && who.role === "approver", { said: url.searchParams.get("said"), problem: url.searchParams.get("problem"), adding: url.searchParams.get("add") === "1" }))}`, { chrome: chromeFor(project, "settings") }));
|
|
178
178
|
}
|
|
179
|
-
|
|
179
|
+
/** D5: subagents were teammates; an old link lands on the same page under Settings → Lead. */
|
|
180
|
+
async function legacySubagentLink(ctx) {
|
|
181
|
+
const { url, response } = ctx;
|
|
182
|
+
const legacy = /^\/teammates(?:\/([1-9][0-9]{0,9})(\/soul\.md)?)?$/.exec(url.pathname);
|
|
183
|
+
return redirect(response, legacy === null || legacy[1] === undefined ? "/settings/lead#subagents" : `/settings/lead/subagents/${legacy[1]}${legacy[2] ?? ""}`);
|
|
184
|
+
}
|
|
185
|
+
async function subagentPage(ctx) {
|
|
180
186
|
const { url, who, response } = ctx;
|
|
181
|
-
const mate =
|
|
187
|
+
const mate = visibleSubagent(who, Number(pathPart(url, 4)));
|
|
182
188
|
if (mate === null)
|
|
183
|
-
return refuse(response, who, 404, "No such
|
|
189
|
+
return refuse(response, who, 404, "No such subagent in your projects.", "/settings/lead/subagents");
|
|
184
190
|
const approvers = store.listApprovers().map(one => one.name).filter(name => store.accountCanAccess(name, mate.repo));
|
|
185
|
-
return sendScreen(response, 200, screen(labelOf(mate), html `<h1>${labelOf(mate)}</h1>${(
|
|
191
|
+
return sendScreen(response, 200, screen(labelOf(mate), html `<p><a href="/settings/lead">Lead</a></p><h1>${labelOf(mate)}</h1>${(subagentPageHtml(store, mate, who.name, projectName, who.via === "cookie" && who.role === "approver", approvers, { said: url.searchParams.get("said"), problem: url.searchParams.get("problem"), query: url.searchParams.get("q") }))}`, { chrome: chromeFor(mate.repo, "settings") }));
|
|
186
192
|
}
|
|
187
|
-
async function
|
|
193
|
+
async function subagentSoulFile(ctx) {
|
|
188
194
|
const { url, who, response } = ctx;
|
|
189
|
-
const mate =
|
|
195
|
+
const mate = visibleSubagent(who, Number(pathPart(url, 4)));
|
|
190
196
|
if (mate === null)
|
|
191
|
-
return refuse(response, who, 404, "No such
|
|
197
|
+
return refuse(response, who, 404, "No such subagent in your projects.", "/settings/lead/subagents");
|
|
192
198
|
response.writeHead(200, { ...SAFETY, "Content-Type": "text/markdown; charset=utf-8", "Content-Disposition": `attachment; filename="${mate.handle}.md"` });
|
|
193
199
|
return void response.end(mate.soul);
|
|
194
200
|
}
|
|
@@ -304,69 +310,69 @@ export function createFlowsHandlers(runtime) {
|
|
|
304
310
|
const tried = addKitSample(store, kit, repo, who.name, now);
|
|
305
311
|
if (!tried.ok)
|
|
306
312
|
return page("problem", tried.said);
|
|
307
|
-
// The
|
|
313
|
+
// The subagent picks it up on the worker's next pass (a few seconds); its flow opens on the card.
|
|
308
314
|
try {
|
|
309
315
|
advanceFlows(store, repo, now, { evidenceRoot });
|
|
310
316
|
}
|
|
311
317
|
catch { /* the worker's next pass moves it */ }
|
|
312
318
|
return redirect(response, tried.href);
|
|
313
319
|
};
|
|
314
|
-
// ---- v92: looking after
|
|
315
|
-
async function
|
|
320
|
+
// ---- v92: looking after subagents, and answering their questions -----------
|
|
321
|
+
async function answerSubagentQuestionSend(ctx) {
|
|
316
322
|
const { url, who, request, response, posted } = ctx;
|
|
317
|
-
const body = readForm(posted, CONSOLE_FORMS.
|
|
323
|
+
const body = readForm(posted, CONSOLE_FORMS.subagents);
|
|
318
324
|
const now = clock();
|
|
319
325
|
const wantsJson = (request.headers.accept ?? "").includes("application/json");
|
|
320
326
|
if (who.via !== "cookie")
|
|
321
|
-
return refuse(response, who, 403, "Sign in to do that.", "/
|
|
322
|
-
const question = store.
|
|
327
|
+
return refuse(response, who, 403, "Sign in to do that.", "/settings/lead/subagents");
|
|
328
|
+
const question = store.subagentQuestion(Number(pathPart(url, 5)));
|
|
323
329
|
const card = question === null ? null : store.getFlowCard(question.card);
|
|
324
330
|
const flow = card === null ? null : store.getFlow(card.flow);
|
|
325
331
|
const done = question === null || flow === null || !visible(flow.repo) ? { ok: false, said: "No such question." }
|
|
326
|
-
:
|
|
332
|
+
: answerSubagentQuestion(store, question.id, { choice: body.get("choice"), text: body.get("text"), by: who.name, via: "web" }, now);
|
|
327
333
|
if (wantsJson)
|
|
328
334
|
return respond(response, done.ok ? 200 : 409, "application/json; charset=utf-8", JSON.stringify(done));
|
|
329
|
-
const back = question === null ? "/
|
|
335
|
+
const back = question === null ? "/settings/lead/subagents" : `/settings/lead/subagents/${question.subagent}`;
|
|
330
336
|
return redirect(response, `${back}?${done.ok ? "said" : "problem"}=${encodeURIComponent(done.said)}`);
|
|
331
337
|
}
|
|
332
|
-
async function
|
|
338
|
+
async function newSubagent(ctx) {
|
|
333
339
|
const { who, response, posted } = ctx;
|
|
334
|
-
const body = readForm(posted, CONSOLE_FORMS.
|
|
340
|
+
const body = readForm(posted, CONSOLE_FORMS.subagents);
|
|
335
341
|
const now = clock();
|
|
336
342
|
if (who.via !== "cookie")
|
|
337
|
-
return refuse(response, who, 403, "Sign in to do that.", "/
|
|
343
|
+
return refuse(response, who, 403, "Sign in to do that.", "/settings/lead/subagents");
|
|
338
344
|
const projects = consoleProjects();
|
|
339
345
|
const repo = body.get("repo") ?? "";
|
|
340
346
|
if (!projects.includes(repo))
|
|
341
|
-
return redirect(response, `/
|
|
347
|
+
return redirect(response, `/settings/lead/subagents?problem=${encodeURIComponent("Choose one of your projects.")}`);
|
|
342
348
|
const template = body.get("template") ?? "";
|
|
343
|
-
const made =
|
|
344
|
-
return made.ok ? redirect(response, `/
|
|
349
|
+
const made = createSubagentFrom(store, { repo, template: template === "blank" ? null : template, name: body.get("name"), soul: template === "blank" ? BLANK_SOUL.replace("name: \n", `name: ${(body.get("name") ?? "").trim() || "Sam"}\n`).replace("role: \n", "role: Assistant\n") : null, by: who.name }, now);
|
|
350
|
+
return made.ok ? redirect(response, `/settings/lead/subagents/${made.id}?said=${encodeURIComponent(made.said)}`) : redirect(response, `/settings/lead/subagents?problem=${encodeURIComponent(made.said)}`);
|
|
345
351
|
}
|
|
346
|
-
const
|
|
352
|
+
const subagentAct = (part) => async (ctx) => {
|
|
347
353
|
const { url, who, request, response, posted } = ctx;
|
|
348
|
-
const body = readForm(posted, CONSOLE_FORMS.
|
|
354
|
+
const body = readForm(posted, CONSOLE_FORMS.subagents);
|
|
349
355
|
const now = clock();
|
|
350
356
|
const wantsJson = (request.headers.accept ?? "").includes("application/json");
|
|
351
357
|
if (who.via !== "cookie")
|
|
352
|
-
return refuse(response, who, 403, "Sign in to do that.", "/
|
|
353
|
-
const mate =
|
|
358
|
+
return refuse(response, who, 403, "Sign in to do that.", "/settings/lead/subagents");
|
|
359
|
+
const mate = visibleSubagent(who, Number(pathPart(url, 4)));
|
|
354
360
|
if (mate === null)
|
|
355
|
-
return refuse(response, who, 404, "No such
|
|
356
|
-
const back = `/
|
|
361
|
+
return refuse(response, who, 404, "No such subagent in your projects.", "/settings/lead/subagents");
|
|
362
|
+
const back = `/settings/lead/subagents/${mate.id}`;
|
|
357
363
|
if (part === "soul") {
|
|
358
364
|
const soul = body.get("soul") ?? "";
|
|
359
365
|
const saved = saveSoul(store, mate, soul, who.name, now);
|
|
360
366
|
if (!saved.ok) {
|
|
361
367
|
const approvers = store.listApprovers().map(one => one.name).filter(name => store.accountCanAccess(name, mate.repo));
|
|
362
|
-
return sendScreen(response, 400, screen(labelOf(mate), html `<h1>${labelOf(mate)}</h1>${
|
|
368
|
+
return sendScreen(response, 400, screen(labelOf(mate), html `<h1>${labelOf(mate)}</h1>${subagentPageHtml(store, mate, who.name, projectName, true, approvers, { problem: saved.said, soulDraft: soul })}`, { chrome: chromeFor(mate.repo, "flows") }));
|
|
363
369
|
}
|
|
364
370
|
return redirect(response, `${back}?said=${encodeURIComponent(saved.said)}`);
|
|
365
371
|
}
|
|
366
372
|
if (part === "week") {
|
|
367
373
|
// v97: undo one of its tool calls, or send the week's report now.
|
|
368
374
|
const done = body.get("op") === "undo" ? await undoCall(store, mate, Number(body.get("id")), who.name, { toolHome }, now)
|
|
369
|
-
:
|
|
375
|
+
: sendSubagentWeeklies(store, mate.repo, now, mate.id) > 0 ? { ok: true, said: `Sent the week's report to ${mate.manager}.` } : { ok: false, said: "The report couldn't be sent." };
|
|
370
376
|
if (wantsJson)
|
|
371
377
|
return respond(response, done.ok ? 200 : 409, "application/json; charset=utf-8", JSON.stringify(done));
|
|
372
378
|
return redirect(response, `${back}?${done.ok ? "said" : "problem"}=${encodeURIComponent(done.said)}#week`);
|
|
@@ -395,18 +401,18 @@ export function createFlowsHandlers(runtime) {
|
|
|
395
401
|
if (part === "tools") {
|
|
396
402
|
// v94: which project tools it may use, and its rule for each action.
|
|
397
403
|
const tool = body.get("tool") ?? "", op = body.get("op");
|
|
398
|
-
const grant = store.
|
|
404
|
+
const grant = store.subagentGrant(mate.id, tool);
|
|
399
405
|
const changed = op === "grant" ? await grantTool(store, mate, tool, who.name, now, { toolHome })
|
|
400
406
|
: op === "revoke" ? revokeTool(store, mate, tool, who.name, now)
|
|
401
407
|
: grant === null ? { ok: false, said: `${nameOf(mate)} doesn't use ${tool}.` } : setToolRules(store, mate, tool, rulesFromForm(grant, key => body.sent.get(key)), who.name, now);
|
|
402
408
|
return redirect(response, `${back}?${changed.ok ? "said" : "problem"}=${encodeURIComponent(changed.said)}#tools`);
|
|
403
409
|
}
|
|
404
|
-
const done = part === "state" ?
|
|
405
|
-
: part === "note" ?
|
|
406
|
-
: part === "settings" ?
|
|
407
|
-
:
|
|
410
|
+
const done = part === "state" ? setSubagentState(store, mate, body.get("state") === "removed" ? "removed" : body.get("state") === "paused" ? "paused" : "active", who.name, now)
|
|
411
|
+
: part === "note" ? tellSubagent(store, mate, body.get("note") ?? "", who.name, now)
|
|
412
|
+
: part === "settings" ? subagentSettings(store, mate, { model: body.get("model") ?? "default", dailyTurns: Number(body.get("dailyTurns")), manager: body.get("manager") ?? mate.manager }, who.name, now)
|
|
413
|
+
: sendSubagentSummaries(store, mate.repo, now, mate.id) > 0 ? { ok: true, said: `Sent today's summary to ${mate.manager}.` } : { ok: false, said: "The summary couldn't be sent." };
|
|
408
414
|
if (part === "state" && body.get("state") === "removed" && done.ok)
|
|
409
|
-
return redirect(response, `/
|
|
415
|
+
return redirect(response, `/settings/lead/subagents?said=${encodeURIComponent(done.said)}`);
|
|
410
416
|
return redirect(response, `${back}?${done.ok ? "said" : "problem"}=${encodeURIComponent(done.said)}${part === "note" ? "#memory" : ""}`);
|
|
411
417
|
};
|
|
412
418
|
// ---- flows: making one -----------------------------------------------------
|
|
@@ -839,9 +845,10 @@ export function createFlowsHandlers(runtime) {
|
|
|
839
845
|
"flows.page": flowsPage,
|
|
840
846
|
"kits": kitsGallery,
|
|
841
847
|
"kit.page": kitPage,
|
|
842
|
-
"
|
|
843
|
-
"
|
|
844
|
-
"
|
|
848
|
+
"subagents": subagentsPage,
|
|
849
|
+
"subagents.legacy": legacySubagentLink,
|
|
850
|
+
"subagent.page": subagentPage,
|
|
851
|
+
"subagent.soul-file": subagentSoulFile,
|
|
845
852
|
"flow.insights": flowInsightsRead,
|
|
846
853
|
"flow.run": flowRunRead,
|
|
847
854
|
"flow.export": flowExportFile,
|
|
@@ -858,17 +865,17 @@ export function createFlowsHandlers(runtime) {
|
|
|
858
865
|
"kit.setup": kitAct("setup"),
|
|
859
866
|
"kit.sample": kitAct("sample"),
|
|
860
867
|
"kit.github": kitAct("github"),
|
|
861
|
-
"
|
|
862
|
-
"
|
|
863
|
-
"
|
|
864
|
-
"
|
|
865
|
-
"
|
|
866
|
-
"
|
|
867
|
-
"
|
|
868
|
-
"
|
|
869
|
-
"
|
|
870
|
-
"
|
|
871
|
-
"
|
|
868
|
+
"subagent.new": newSubagent,
|
|
869
|
+
"subagent.soul": subagentAct("soul"),
|
|
870
|
+
"subagent.state": subagentAct("state"),
|
|
871
|
+
"subagent.note": subagentAct("note"),
|
|
872
|
+
"subagent.settings": subagentAct("settings"),
|
|
873
|
+
"subagent.summary": subagentAct("summary"),
|
|
874
|
+
"subagent.tools": subagentAct("tools"),
|
|
875
|
+
"subagent.memory": subagentAct("memory"),
|
|
876
|
+
"subagent.routines": subagentAct("routines"),
|
|
877
|
+
"subagent.week": subagentAct("week"),
|
|
878
|
+
"subagent.answer": answerSubagentQuestionSend,
|
|
872
879
|
"flows.gallery-create": createFromGallery,
|
|
873
880
|
"flows.create": createFlow,
|
|
874
881
|
"flows.example": createExampleFlow,
|
package/dist/server/guards.js
CHANGED
|
@@ -206,7 +206,7 @@ export function createSharedGuards(runtime) {
|
|
|
206
206
|
if (route?.limited === "self")
|
|
207
207
|
return true;
|
|
208
208
|
if (route?.limited === "proposal") {
|
|
209
|
-
const proposal = runtime.store.
|
|
209
|
+
const proposal = runtime.store.getLeadProposal(Number(path.split('/')[3])), action = proposal?.kind === 'action' ? sharedActionPayload(proposal.payload) : null;
|
|
210
210
|
const shared = proposal ? runtime.store.handle.prepare('SELECT id FROM team_conversation WHERE thread=?').get(proposal.thread) : null;
|
|
211
211
|
if (shared && who.via === 'cookie') {
|
|
212
212
|
try {
|
|
@@ -216,10 +216,10 @@ export function createSharedGuards(runtime) {
|
|
|
216
216
|
}
|
|
217
217
|
catch { /* The same scoped refusal below also covers revoked membership. */ }
|
|
218
218
|
}
|
|
219
|
-
if (action && proposal && runtime.store.
|
|
219
|
+
if (action && proposal && runtime.store.getLeadThread(proposal.thread)?.approver === who.name && visible(action.repo) && runtime.store.accountCanAccess(who.name, action.repo))
|
|
220
220
|
return true;
|
|
221
221
|
// A card about the person themselves (what their lead knows about them) is in no project.
|
|
222
|
-
if (action && proposal && action.repo === '' && OWNER_ACTIONS.has(action.operation) && runtime.store.
|
|
222
|
+
if (action && proposal && action.repo === '' && OWNER_ACTIONS.has(action.operation) && runtime.store.getLeadThread(proposal.thread)?.approver === who.name)
|
|
223
223
|
return true;
|
|
224
224
|
refuse(response, who, 404, 'No such action in your projects.', '/projects');
|
|
225
225
|
return false;
|
package/dist/server/http.d.ts
CHANGED
|
@@ -13,7 +13,7 @@ import { type cloneGithubRepo, type listGithubRepos, type previewGithubRepo } fr
|
|
|
13
13
|
import { type PublishExec } from "../publish.js";
|
|
14
14
|
import { type ResultTab } from "../result-review.js";
|
|
15
15
|
import { type Store } from "../store.js";
|
|
16
|
-
import { type
|
|
16
|
+
import { type SubscriptionLeadRunner } from "../subscription-chat.js";
|
|
17
17
|
import { type launchRuntimeUpdate } from "../toolroll-update.js";
|
|
18
18
|
import { type IncomingMessage, type ServerResponse } from "node:http";
|
|
19
19
|
export type ServeOptions = {
|
|
@@ -124,7 +124,7 @@ export type ServeOptions = {
|
|
|
124
124
|
chatFetcher?: typeof fetch;
|
|
125
125
|
/** Subscription-backed mate transport; injected in tests so no real
|
|
126
126
|
* Codex or Claude membership turn is consumed. */
|
|
127
|
-
subscriptionChatRunner?:
|
|
127
|
+
subscriptionChatRunner?: SubscriptionLeadRunner;
|
|
128
128
|
/** Tests: stands in for `codex mcp list --json` in the project (the Tools page's "Found on this computer"). */
|
|
129
129
|
codexToolList?: (cwd: string) => Promise<string | null>;
|
|
130
130
|
/** Tests: the home whose ~/.toolroll (or older ~/.standing-orders) tool-secrets and ~/.claude.json the Tools page uses. */
|
|
@@ -185,7 +185,7 @@ export type ServeOptions = {
|
|
|
185
185
|
publishExec?: PublishExec;
|
|
186
186
|
};
|
|
187
187
|
export declare const BODY_CAP: number;
|
|
188
|
-
/** How long a stop waits for
|
|
188
|
+
/** How long a stop waits for subagents and the lead's follow pass before closing anyway. */
|
|
189
189
|
export declare const SHUTDOWN_WAIT_MS = 5000;
|
|
190
190
|
/**
|
|
191
191
|
* Match `/t/<id>` (suffix "") or `/t/<id>/<verb>` — the id percent-decoded
|
package/dist/server/http.js
CHANGED
|
@@ -23,7 +23,7 @@ import { SIGN_IN_LINK_PATH } from "./session.js";
|
|
|
23
23
|
// A note is at most NOTE_BYTE_CAP (16,000) UTF-8 bytes, which URL encoding
|
|
24
24
|
// can triple: room for one whole, before canonical text validation.
|
|
25
25
|
export const BODY_CAP = 64 * 1024;
|
|
26
|
-
/** How long a stop waits for
|
|
26
|
+
/** How long a stop waits for subagents and the lead's follow pass before closing anyway. */
|
|
27
27
|
export const SHUTDOWN_WAIT_MS = 5_000;
|
|
28
28
|
// ---- path plumbing ---------------------------------------------------------
|
|
29
29
|
/**
|
package/dist/server/live.js
CHANGED
|
@@ -50,7 +50,7 @@ export function parseLiveRoom(name) {
|
|
|
50
50
|
}
|
|
51
51
|
const json = (response, status, value) => respond(response, status, "application/json", JSON.stringify(value));
|
|
52
52
|
export function createLiveHandlers(runtime, live) {
|
|
53
|
-
const { store, identify, liveCeiling, familyOf, taskRooms, flowRooms, clock,
|
|
53
|
+
const { store, identify, liveCeiling, familyOf, taskRooms, flowRooms, clock, leadPrincipal, taskChatFocus, chatScopeOf, liveTurns, team, visible } = runtime;
|
|
54
54
|
// The reader's workspace: one room for everyone, nudged by any meaningful write or a clock-bound lapse.
|
|
55
55
|
const workspaceRooms = createLiveRooms(() => `${live.workspaceRevision.current()}:${live.workspaceRevision.expiresAt(clock())}`, null, { bus: live.bus, minIntervalMs: WORKSPACE_SETTLE_MS });
|
|
56
56
|
// A team audience is per actor (and per token): its key carries who reads, the room keeps how to read as them.
|
|
@@ -124,7 +124,7 @@ export function createLiveHandlers(runtime, live) {
|
|
|
124
124
|
/** A reply starts on a thread: whoever has that conversation open follows it. */
|
|
125
125
|
function turnStarted(thread) {
|
|
126
126
|
for (const viewer of chatViewers) {
|
|
127
|
-
if (admitted(viewer) && store.
|
|
127
|
+
if (admitted(viewer) && store.liveLeadThreadFor(viewer.name, viewer.scope)?.id === thread)
|
|
128
128
|
follow(viewer, thread);
|
|
129
129
|
}
|
|
130
130
|
}
|
|
@@ -211,7 +211,7 @@ export function createLiveHandlers(runtime, live) {
|
|
|
211
211
|
const browser = who;
|
|
212
212
|
if (who.role !== "approver")
|
|
213
213
|
return json(response, 403, { error: "session" });
|
|
214
|
-
if (
|
|
214
|
+
if (leadPrincipal(browser) === null)
|
|
215
215
|
return json(response, 403, { error: "standing" });
|
|
216
216
|
const focusTask = room.task === null ? null : taskChatFocus(room.task, now, who, { mintNonce: false });
|
|
217
217
|
if (room.task !== null && focusTask === null)
|
|
@@ -224,10 +224,10 @@ export function createLiveHandlers(runtime, live) {
|
|
|
224
224
|
const again = readBrowser(request, browser);
|
|
225
225
|
if (again === null || again.role !== "approver")
|
|
226
226
|
return false;
|
|
227
|
-
const principal =
|
|
227
|
+
const principal = leadPrincipal(again);
|
|
228
228
|
if (principal === null)
|
|
229
229
|
return false;
|
|
230
|
-
const thread = store.
|
|
230
|
+
const thread = store.liveLeadThreadFor(again.name, scope);
|
|
231
231
|
// Even the default lead room is bound to the projects admitted when its thread opened.
|
|
232
232
|
if (thread !== null && thread.ceilingDigest !== principal.ceilingDigest)
|
|
233
233
|
return false;
|
|
@@ -251,7 +251,7 @@ export function createLiveHandlers(runtime, live) {
|
|
|
251
251
|
chatViewers.add(viewer);
|
|
252
252
|
const unregister = connection.onClose(() => { viewer.detach?.(); chatViewers.delete(viewer); });
|
|
253
253
|
const unprove = connection.onKeepAlive(() => { admitted(viewer); });
|
|
254
|
-
const thread = store.
|
|
254
|
+
const thread = store.liveLeadThreadFor(who.name, scope);
|
|
255
255
|
if (thread !== null)
|
|
256
256
|
follow(viewer, thread.id);
|
|
257
257
|
});
|
|
@@ -612,7 +612,7 @@ export function createPeopleHandlers(runtime) {
|
|
|
612
612
|
/**
|
|
613
613
|
* Back from a service's sign-in: the code becomes the tool's tokens,
|
|
614
614
|
* kept in its secrets file, and a page sends the person back to Tools (or
|
|
615
|
-
* to the kit the Connect came from, whose
|
|
615
|
+
* to the kit the Connect came from, whose subagent may then use the tool).
|
|
616
616
|
*/
|
|
617
617
|
/** v100: back from the identity provider. Proves the person, then hands them to /login/sso/finish on this site. */
|
|
618
618
|
async function ssoCallback(request, response, url) {
|
package/dist/server/remote.js
CHANGED
|
@@ -138,6 +138,8 @@ export function createRemoteHandlers(runtime) {
|
|
|
138
138
|
return;
|
|
139
139
|
return respond(response, 404, 'text/plain; charset=utf-8', 'No such address.');
|
|
140
140
|
};
|
|
141
|
+
// D5: native coding sessions and the central team service are deprecated (still served this release); each
|
|
142
|
+
// answer says so in a Deprecation header (RFC 9745).
|
|
141
143
|
// Each protocol adapter keeps its own operation boundary; every row still names its own entry.
|
|
142
144
|
const registrations = handlersOf("remote", {}, {
|
|
143
145
|
"edge.telegram-hook": async ({ request, response }) => { await telegramHook(hookContext, request, response); },
|
|
@@ -150,16 +152,16 @@ export function createRemoteHandlers(runtime) {
|
|
|
150
152
|
"edge.oauth-token": async ({ request, response, url }) => { await oauthHttp(request, response, url); },
|
|
151
153
|
"edge.oauth-authorize": async ({ request, response, url }) => { await oauthHttp(request, response, url); },
|
|
152
154
|
"edge.oauth-consent": async ({ request, response, url }) => { await oauthHttp(request, response, url); },
|
|
153
|
-
"edge.sessions-list": async ({ request, response }) => { await sessionEndpoint(request, response); },
|
|
154
|
-
"edge.sessions-show": async ({ request, response }) => { await sessionEndpoint(request, response); },
|
|
155
|
-
"edge.sessions-changes": async ({ request, response }) => { await sessionEndpoint(request, response); },
|
|
156
|
-
"edge.sessions-start": async ({ request, response }) => { await sessionEndpoint(request, response); },
|
|
157
|
-
"edge.sessions-send": async ({ request, response }) => { await sessionEndpoint(request, response); },
|
|
158
|
-
"edge.sessions-stop": async ({ request, response }) => { await sessionEndpoint(request, response); },
|
|
159
|
-
"edge.sessions-resume": async ({ request, response }) => { await sessionEndpoint(request, response); },
|
|
160
|
-
"edge.sessions-recover": async ({ request, response }) => { await sessionEndpoint(request, response); },
|
|
161
|
-
"edge.team-read": async ({ request, response }) => { await teamEndpoint(request, response); },
|
|
162
|
-
"edge.team-send": async ({ request, response }) => { await teamEndpoint(request, response); },
|
|
155
|
+
"edge.sessions-list": async ({ request, response }) => { response.setHeader('Deprecation', 'true'); await sessionEndpoint(request, response); },
|
|
156
|
+
"edge.sessions-show": async ({ request, response }) => { response.setHeader('Deprecation', 'true'); await sessionEndpoint(request, response); },
|
|
157
|
+
"edge.sessions-changes": async ({ request, response }) => { response.setHeader('Deprecation', 'true'); await sessionEndpoint(request, response); },
|
|
158
|
+
"edge.sessions-start": async ({ request, response }) => { response.setHeader('Deprecation', 'true'); await sessionEndpoint(request, response); },
|
|
159
|
+
"edge.sessions-send": async ({ request, response }) => { response.setHeader('Deprecation', 'true'); await sessionEndpoint(request, response); },
|
|
160
|
+
"edge.sessions-stop": async ({ request, response }) => { response.setHeader('Deprecation', 'true'); await sessionEndpoint(request, response); },
|
|
161
|
+
"edge.sessions-resume": async ({ request, response }) => { response.setHeader('Deprecation', 'true'); await sessionEndpoint(request, response); },
|
|
162
|
+
"edge.sessions-recover": async ({ request, response }) => { response.setHeader('Deprecation', 'true'); await sessionEndpoint(request, response); },
|
|
163
|
+
"edge.team-read": async ({ request, response }) => { response.setHeader('Deprecation', 'true'); await teamEndpoint(request, response); },
|
|
164
|
+
"edge.team-send": async ({ request, response }) => { response.setHeader('Deprecation', 'true'); await teamEndpoint(request, response); },
|
|
163
165
|
"edge.cli": async ({ request, response }) => { await cliEndpoint(request, response); },
|
|
164
166
|
"edge.teams": teams,
|
|
165
167
|
});
|
|
@@ -2,10 +2,10 @@ import { type AssignmentSnapshot } from "../assignment.js";
|
|
|
2
2
|
import { type BrowserActionCard } from "../browser-workspace.js";
|
|
3
3
|
import { type ChatDraft } from "../converse.js";
|
|
4
4
|
import { type DispatchDiagnosis } from "../dispatch.js";
|
|
5
|
-
import { type
|
|
5
|
+
import { type LeadLiveStep } from "../lead-progress.js";
|
|
6
6
|
import { type FailureExplanation } from "../needs-you.js";
|
|
7
7
|
import { type Scope } from "../scope.js";
|
|
8
|
-
import { type ChatConfig, type ChatProviderId, type ChatSnapshot, type ChatTurn, type CheckProgress, type CoordinatorProposal, type Decision, type DirectChatProviderId, type
|
|
8
|
+
import { type ChatConfig, type ChatProviderId, type ChatSnapshot, type ChatTurn, type CheckProgress, type CoordinatorProposal, type Decision, type DirectChatProviderId, type LeadAsk, type LeadMessage, type LeadProposal, type LeadSession, type LeadTurn, type Publication, type RepairChainRow, type Store, type SubscriptionChatProviderId, type TaskFamily, type TaskState } from "../store.js";
|
|
9
9
|
import { type TaskControlView } from "../task-control.js";
|
|
10
10
|
import { type TeamChatProviderResolver } from "../team-chat-authorization.js";
|
|
11
11
|
import { type TeamSnapshot } from "../team-contract.js";
|
|
@@ -126,14 +126,14 @@ export type AssignmentChatSnapshot = ChatSnapshot & {
|
|
|
126
126
|
};
|
|
127
127
|
export declare function chatFleetOverview(snapshot: AssignmentChatSnapshot | null, projects: readonly ChatProjectPulse[], interactive: boolean): Html;
|
|
128
128
|
/**
|
|
129
|
-
* The
|
|
129
|
+
* The lead's project rail: one bounded pulse per admitted project, plus
|
|
130
130
|
* two roads that preserve the plane's contracts. "ask" sends the stable
|
|
131
131
|
* rN alias the model already sees; "board" uses the existing POST switch
|
|
132
132
|
* instead of smuggling a project change through a GET parameter.
|
|
133
133
|
*/
|
|
134
134
|
export declare function chatProjectRail(projects: readonly ChatProjectPulse[], inert: boolean): Html;
|
|
135
135
|
/** Spend-authorized one-click questions: ordinary /chat posts, not a new door. */
|
|
136
|
-
export declare function
|
|
136
|
+
export declare function leadPromptStarters(focus?: TaskChatFocus | null): Html;
|
|
137
137
|
export declare function chatHeading(copy: string, projectCount: number, showProjectToggle?: boolean): Html;
|
|
138
138
|
/** A deliberately small rich-text grammar for model copy. The reply is shaped first (the lead's voice, enforced:
|
|
139
139
|
* no headers, at most three bold anchors, labelled links, no internal ids unless `asked` wanted them); input is
|
|
@@ -204,7 +204,7 @@ export declare function chatPage(chrome: Chrome, data: {
|
|
|
204
204
|
csrf: string;
|
|
205
205
|
problem: string | null;
|
|
206
206
|
/** The card that mints a mate session (mate arc §5), approvers only. */
|
|
207
|
-
|
|
207
|
+
leadMint?: Html;
|
|
208
208
|
/** Pending coordinator proposals as cards (mate arc v3), approvers only. */
|
|
209
209
|
coordinatorProposals?: Html;
|
|
210
210
|
/** The task's result detail (package 3), when the URL opened one. */
|
|
@@ -216,7 +216,7 @@ export declare function chatPage(chrome: Chrome, data: {
|
|
|
216
216
|
}): Screen;
|
|
217
217
|
export declare function chatAckPage(chrome: Chrome, turn: ChatTurn, nonce: string): Screen;
|
|
218
218
|
/** The card that starts a conversation: the one password ceremony (mate arc §1). */
|
|
219
|
-
export declare function
|
|
219
|
+
export declare function leadMintCard(enabled: {
|
|
220
220
|
billing: "metered" | "subscription";
|
|
221
221
|
config: {
|
|
222
222
|
provider: ChatProviderId;
|
|
@@ -230,7 +230,7 @@ export declare function decisionsFor(store: Store, proposals: readonly {
|
|
|
230
230
|
}[]): Map<number, Decision>;
|
|
231
231
|
export type ProposalCardView = {
|
|
232
232
|
id: number;
|
|
233
|
-
kind:
|
|
233
|
+
kind: LeadProposal["kind"];
|
|
234
234
|
payload: Record<string, unknown>;
|
|
235
235
|
state: string;
|
|
236
236
|
outcome: Record<string, unknown> | null;
|
|
@@ -242,7 +242,7 @@ export type ProposalCardView = {
|
|
|
242
242
|
name: string;
|
|
243
243
|
ago: string;
|
|
244
244
|
};
|
|
245
|
-
/** Where confirm/dismiss post: `/chat/proposal` for the
|
|
245
|
+
/** Where confirm/dismiss post: `/chat/proposal` for the lead's, `/proposals` for a coordinator's. */
|
|
246
246
|
actionBase: string;
|
|
247
247
|
};
|
|
248
248
|
/**
|
|
@@ -259,8 +259,8 @@ export declare function proposalCardParts(view: ProposalCardView, inert: boolean
|
|
|
259
259
|
html: Html;
|
|
260
260
|
card: BrowserActionCard;
|
|
261
261
|
};
|
|
262
|
-
export declare function
|
|
263
|
-
export declare function
|
|
262
|
+
export declare function leadProposalCard(proposal: LeadProposal, inert: boolean, decision: Decision | null, returnTo?: string | null): Html;
|
|
263
|
+
export declare function leadProposalCardParts(proposal: LeadProposal, inert: boolean, decision: Decision | null, returnTo?: string | null): {
|
|
264
264
|
html: Html;
|
|
265
265
|
card: BrowserActionCard;
|
|
266
266
|
};
|
|
@@ -269,7 +269,7 @@ export declare function mateProposalCardParts(proposal: MateProposal, inert: boo
|
|
|
269
269
|
export declare function teamProposalCardParts(store: Store, actor: {
|
|
270
270
|
name: string;
|
|
271
271
|
generation: number;
|
|
272
|
-
}, proposal:
|
|
272
|
+
}, proposal: LeadProposal, snapshot: TeamSnapshot, csrf: string, decision: Decision | null, now: Date, provider: TeamChatProviderResolver): {
|
|
273
273
|
html: Html;
|
|
274
274
|
card: BrowserActionCard;
|
|
275
275
|
};
|
|
@@ -278,8 +278,8 @@ export declare function coordinatorProposalCard(proposal: CoordinatorProposal, n
|
|
|
278
278
|
export declare function coordinatorProposalsSection(proposals: readonly CoordinatorProposal[], decisions: Map<number, Decision>, now: Date, heading?: boolean, returnTo?: string | null): Html;
|
|
279
279
|
/** The lead thread a change in reachable projects closed (mate arc ruling 9): its saved words and card outcomes, never continued. */
|
|
280
280
|
export type ReplacedThread = {
|
|
281
|
-
messages:
|
|
282
|
-
proposals:
|
|
281
|
+
messages: LeadMessage[];
|
|
282
|
+
proposals: LeadProposal[];
|
|
283
283
|
decisions: Map<number, Decision>;
|
|
284
284
|
};
|
|
285
285
|
export declare const REPLACED_THREAD_DIVIDER = "New conversation \u2014 the projects I can reach changed";
|
|
@@ -287,33 +287,33 @@ export declare const REPLACED_THREAD_DIVIDER = "New conversation \u2014 the proj
|
|
|
287
287
|
export declare function replacedBrowserMessages(previous: ReplacedThread): import("../browser-workspace.js").BrowserMessage[];
|
|
288
288
|
/** The replaced thread for the server-rendered page: read only, then the divider. */
|
|
289
289
|
export declare function replacedThreadHtml(previous: ReplacedThread | null | undefined): Html;
|
|
290
|
-
export type
|
|
290
|
+
export type LeadThreadRows = {
|
|
291
291
|
/** The lead thread a change in reachable projects replaced; shown only. */
|
|
292
292
|
previous?: ReplacedThread | null;
|
|
293
|
-
messages:
|
|
294
|
-
proposals:
|
|
293
|
+
messages: LeadMessage[];
|
|
294
|
+
proposals: LeadProposal[];
|
|
295
295
|
/** The decisions the answer cards name. */
|
|
296
296
|
decisions: Map<number, Decision>;
|
|
297
297
|
coordinatorProposals: CoordinatorProposal[];
|
|
298
|
-
pending:
|
|
299
|
-
recent:
|
|
298
|
+
pending: LeadTurn | null;
|
|
299
|
+
recent: LeadTurn[];
|
|
300
300
|
/** Optional task lens into the same unified thread. */
|
|
301
301
|
focusTask: TaskChatFocus | null;
|
|
302
302
|
/** The lead's open question to this reader, drawn as buttons under its reply. */
|
|
303
|
-
ask?:
|
|
303
|
+
ask?: LeadAsk | null;
|
|
304
304
|
/** Every question the lead asked in these messages, by turn: answered ones show their words without buttons. */
|
|
305
|
-
asks?: Map<number,
|
|
305
|
+
asks?: Map<number, LeadAsk>;
|
|
306
306
|
};
|
|
307
307
|
/** The lead's question as buttons: each option sends itself as the next message (the same POST as a typed one);
|
|
308
308
|
* "Something else" moves to the composer. Nothing shows while a reply is running. */
|
|
309
|
-
export declare function
|
|
309
|
+
export declare function leadAskHtml(ask: LeadAsk, target: {
|
|
310
310
|
task: string | null;
|
|
311
311
|
project: string | null;
|
|
312
312
|
}, composer: string, open?: boolean): Html;
|
|
313
313
|
/** The thread's messages as the React conversation renders them, each
|
|
314
314
|
* with the proposal cards its turn produced; `back` is where a card's
|
|
315
315
|
* confirm or dismiss returns. */
|
|
316
|
-
export declare function
|
|
316
|
+
export declare function leadBrowserMessages(rows: Pick<LeadThreadRows, "messages" | "proposals" | "decisions" | "pending" | "ask" | "asks">, back: string | null, target?: {
|
|
317
317
|
task: string | null;
|
|
318
318
|
project: string | null;
|
|
319
319
|
}): import("../browser-workspace.js").BrowserMessage[];
|
|
@@ -323,14 +323,14 @@ export declare function mateBrowserMessages(rows: Pick<MateThreadRows, "messages
|
|
|
323
323
|
* decisions the cards name, and the task lens's own facts — and nothing
|
|
324
324
|
* that merely ticks: no relative age, no freshly minted nonce, no csrf.
|
|
325
325
|
* Equal versions mean equal fragments; the poll fetches nothing else. */
|
|
326
|
-
export declare function
|
|
326
|
+
export declare function leadChatVersion(rows: LeadThreadRows): string;
|
|
327
327
|
/** The thread region — the one safe region the live refresh reconciles
|
|
328
328
|
* (package 2): coordinator cards, the operator/assistant messages with
|
|
329
329
|
* their cards, the reply-in-progress card, and the starters that follow a
|
|
330
330
|
* populated thread. Every child carries a stable `data-key` so the page
|
|
331
331
|
* keeps an unchanged node (its open disclosures, its focus) and replaces
|
|
332
332
|
* only what the server rendered differently. The composer is never here. */
|
|
333
|
-
export declare function
|
|
333
|
+
export declare function leadThreadHtml(data: LeadThreadRows & {
|
|
334
334
|
csrf: string;
|
|
335
335
|
now: Date;
|
|
336
336
|
problem: string | null;
|
|
@@ -338,13 +338,13 @@ export declare function mateThreadHtml(data: MateThreadRows & {
|
|
|
338
338
|
}): Html;
|
|
339
339
|
/** What follows the composer (package 2): the starters of an EMPTY thread
|
|
340
340
|
* sit under the box; once the first message lands they move above it. */
|
|
341
|
-
export declare function
|
|
342
|
-
messages:
|
|
343
|
-
pending:
|
|
341
|
+
export declare function leadAfterComposerHtml(data: {
|
|
342
|
+
messages: LeadMessage[];
|
|
343
|
+
pending: LeadTurn | null;
|
|
344
344
|
focusTask: TaskChatFocus | null;
|
|
345
345
|
}): Html;
|
|
346
|
-
export declare function
|
|
347
|
-
session:
|
|
346
|
+
export declare function leadPage(chrome: Chrome, data: LeadThreadRows & {
|
|
347
|
+
session: LeadSession;
|
|
348
348
|
/** A project's own thread (v77); null for the lead conversation or a task. */
|
|
349
349
|
chatProject?: string | null;
|
|
350
350
|
follow?: {
|
|
@@ -369,7 +369,7 @@ export declare function matePage(chrome: Chrome, data: MateThreadRows & {
|
|
|
369
369
|
* each step's tools in plain words and its text as it is written. Memory
|
|
370
370
|
* only and display only; the saved turn stays the record. */
|
|
371
371
|
export type LiveTurn = {
|
|
372
|
-
steps:
|
|
372
|
+
steps: LeadLiveStep[];
|
|
373
373
|
done: boolean;
|
|
374
374
|
ok: boolean;
|
|
375
375
|
listeners: Set<() => void>;
|