toolroll 0.9.36 → 0.9.37
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 +58 -0
- package/dist/assignment-adapters.d.ts +12 -48
- package/dist/assignment-adapters.js +33 -43
- package/dist/build-review.d.ts +1 -1
- package/dist/build-review.js +2 -1
- package/dist/chat-acceptance.d.ts +1 -1
- package/dist/chat-actions.d.ts +18 -12
- package/dist/chat-actions.js +15 -65
- package/dist/chat-ask.js +5 -5
- package/dist/chat-decide.d.ts +14 -1
- package/dist/chat-decide.js +12 -6
- package/dist/chat-delivery-state.d.ts +12 -70
- package/dist/chat-delivery-state.js +17 -135
- package/dist/chat-delivery.js +58 -30
- package/dist/chat-flow.js +8 -6
- package/dist/chat-inbox.js +1 -1
- package/dist/coding-context.d.ts +2 -39
- package/dist/coding-context.js +2 -1
- package/dist/coding-handoff.d.ts +6 -25
- package/dist/coding-handoff.js +11 -5
- package/dist/coding-types.d.ts +2 -26
- package/dist/coding-workspace.d.ts +2 -0
- package/dist/coding-workspace.js +50 -14
- package/dist/contracts/acceptance-terms.d.ts +14 -0
- package/dist/contracts/acceptance-terms.js +16 -0
- package/dist/contracts/chat-actions.d.ts +328 -0
- package/dist/contracts/chat-actions.js +133 -0
- package/dist/contracts/chat-callback-rows.d.ts +59 -0
- package/dist/contracts/chat-callback-rows.js +46 -0
- package/dist/contracts/chat-content.d.ts +276 -0
- package/dist/contracts/chat-content.js +127 -0
- package/dist/contracts/chat-tables.d.ts +6 -0
- package/dist/contracts/chat-tables.js +136 -0
- package/dist/contracts/coding-context.d.ts +97 -0
- package/dist/contracts/coding-context.js +60 -0
- package/dist/contracts/coding-handoff.d.ts +44 -0
- package/dist/contracts/coding-handoff.js +47 -0
- package/dist/contracts/coding-workspace.d.ts +165 -0
- package/dist/contracts/coding-workspace.js +71 -0
- package/dist/contracts/contract.d.ts +7 -2
- package/dist/contracts/contract.js +21 -12
- package/dist/contracts/decision.d.ts +45 -0
- package/dist/contracts/decision.js +45 -0
- package/dist/contracts/discord-callback.d.ts +45 -0
- package/dist/contracts/discord-callback.js +34 -0
- package/dist/contracts/flow-card.d.ts +50 -0
- package/dist/contracts/flow-card.js +46 -0
- package/dist/contracts/flow-send.d.ts +119 -0
- package/dist/contracts/flow-send.js +112 -0
- package/dist/contracts/flow.d.ts +5 -0
- package/dist/contracts/flow.js +5 -0
- package/dist/contracts/gateway-tools.d.ts +374 -0
- package/dist/contracts/gateway-tools.js +94 -0
- package/dist/contracts/lead-context.d.ts +165 -0
- package/dist/contracts/lead-context.js +73 -0
- package/dist/contracts/lead-tools.d.ts +1905 -0
- package/dist/contracts/lead-tools.js +265 -0
- package/dist/contracts/memory-pass.d.ts +158 -0
- package/dist/contracts/memory-pass.js +102 -0
- package/dist/contracts/project-knowledge.d.ts +126 -0
- package/dist/contracts/project-knowledge.js +93 -0
- package/dist/contracts/project-memory.d.ts +117 -0
- package/dist/contracts/project-memory.js +51 -0
- package/dist/contracts/project-skills.d.ts +121 -0
- package/dist/contracts/project-skills.js +76 -0
- package/dist/contracts/review-findings.d.ts +46 -0
- package/dist/contracts/review-findings.js +48 -0
- package/dist/contracts/route.d.ts +484 -0
- package/dist/contracts/route.js +128 -0
- package/dist/contracts/scope.d.ts +105 -0
- package/dist/contracts/scope.js +114 -0
- package/dist/contracts/scout-report.d.ts +234 -0
- package/dist/contracts/scout-report.js +141 -0
- package/dist/contracts/slack-callback.d.ts +43 -0
- package/dist/contracts/slack-callback.js +35 -0
- package/dist/contracts/sort-answer.d.ts +83 -0
- package/dist/contracts/sort-answer.js +77 -0
- package/dist/contracts/stage-output.d.ts +127 -0
- package/dist/contracts/stage-output.js +166 -0
- package/dist/contracts/task-sizing.d.ts +24 -0
- package/dist/contracts/task-sizing.js +28 -0
- package/dist/contracts/teammate-turn.d.ts +43 -0
- package/dist/contracts/teammate-turn.js +51 -0
- package/dist/contracts/teams-callback.d.ts +14 -0
- package/dist/contracts/teams-callback.js +14 -0
- package/dist/contracts/telegram-callback.d.ts +120 -0
- package/dist/contracts/telegram-callback.js +97 -0
- package/dist/decision.d.ts +11 -20
- package/dist/decision.js +86 -167
- package/dist/desktop-update.d.ts +2 -2
- package/dist/discord-chat.js +31 -20
- package/dist/flow-engine.js +14 -17
- package/dist/flow-items.d.ts +4 -13
- package/dist/flow-items.js +1 -15
- package/dist/flow-send.d.ts +6 -37
- package/dist/flow-send.js +18 -14
- package/dist/flow-share.js +7 -1
- package/dist/flow-sort.d.ts +7 -26
- package/dist/flow-sort.js +25 -20
- package/dist/flow-steps.js +3 -2
- package/dist/flows.d.ts +2 -4
- package/dist/flows.js +9 -5
- package/dist/invoke.js +4 -4
- package/dist/lead-context.d.ts +4 -2
- package/dist/lead-context.js +24 -17
- package/dist/mate-tools.d.ts +4 -0
- package/dist/mate-tools.js +108 -275
- package/dist/mcp-connect.d.ts +24 -4
- package/dist/mcp-connect.js +78 -15
- package/dist/mcp.js +84 -216
- package/dist/memory-pass.d.ts +17 -42
- package/dist/memory-pass.js +54 -26
- package/dist/phase-routing.d.ts +19 -72
- package/dist/phase-routing.js +34 -164
- package/dist/project-knowledge.d.ts +16 -35
- package/dist/project-knowledge.js +42 -21
- package/dist/project-memory.d.ts +2 -28
- package/dist/project-memory.js +28 -13
- package/dist/project-skills.d.ts +16 -38
- package/dist/project-skills.js +41 -32
- package/dist/project-tools.d.ts +1 -0
- package/dist/project-tools.js +4 -4
- package/dist/provider.d.ts +2 -0
- package/dist/provider.js +4 -16
- package/dist/result-shots.d.ts +1 -1
- package/dist/result-shots.js +2 -1
- package/dist/review-switch.d.ts +3 -8
- package/dist/reviewer.d.ts +8 -12
- package/dist/reviewer.js +11 -35
- package/dist/scope.d.ts +21 -43
- package/dist/scope.js +42 -128
- package/dist/scout-report.d.ts +9 -194
- package/dist/scout-report.js +113 -264
- package/dist/scout.js +15 -11
- package/dist/serve.js +9 -2
- package/dist/setup-guide.d.ts +2 -2
- package/dist/slack-chat.js +26 -20
- package/dist/slack-state.js +2 -1
- package/dist/store.d.ts +9 -32
- package/dist/store.js +18 -15
- package/dist/structured-output.js +2 -1
- package/dist/subscription-chat.d.ts +4 -0
- package/dist/subscription-chat.js +4 -1
- package/dist/task-review-brief.d.ts +1 -7
- package/dist/task-review-brief.js +6 -6
- package/dist/task-sizing.d.ts +3 -27
- package/dist/task-sizing.js +11 -26
- package/dist/task-text.d.ts +0 -5
- package/dist/task-text.js +1 -3
- package/dist/teammate-question.js +7 -5
- package/dist/teammate-work.js +9 -5
- package/dist/teammates.d.ts +13 -64
- package/dist/teammates.js +32 -33
- package/dist/teams-chat.js +20 -11
- package/dist/telegram-flow.js +4 -3
- package/dist/telegram-mate.d.ts +4 -14
- package/dist/telegram-mate.js +8 -7
- package/dist/telegram-team.d.ts +2 -19
- package/dist/telegram.d.ts +1 -1
- package/dist/telegram.js +52 -42
- package/dist/text-limits.d.ts +142 -1
- package/dist/text-limits.js +144 -1
- package/dist/tools-ui.d.ts +2 -1
- package/dist/tools-ui.js +7 -4
- package/package.json +1 -1
package/dist/telegram-team.d.ts
CHANGED
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
import type { Store } from "./store.js";
|
|
10
10
|
import { type InlineButton } from "./telegram-mate.js";
|
|
11
11
|
import type { TelegramTransport } from "./telegram.js";
|
|
12
|
+
import type { TelegramMessage } from "./contracts/telegram-callback.js";
|
|
12
13
|
export type TeamCommand = {
|
|
13
14
|
kind: "list";
|
|
14
15
|
} | {
|
|
@@ -36,25 +37,7 @@ export type TeamInbound = {
|
|
|
36
37
|
projects: readonly string[] | null;
|
|
37
38
|
phoneOrigin: (() => string | null) | undefined;
|
|
38
39
|
updateId: number;
|
|
39
|
-
message:
|
|
40
|
-
message_id: number;
|
|
41
|
-
text?: string;
|
|
42
|
-
chat?: {
|
|
43
|
-
id: number;
|
|
44
|
-
type?: string;
|
|
45
|
-
};
|
|
46
|
-
from?: {
|
|
47
|
-
id: number;
|
|
48
|
-
};
|
|
49
|
-
reply_to_message?: {
|
|
50
|
-
message_id: number;
|
|
51
|
-
};
|
|
52
|
-
forward_origin?: unknown;
|
|
53
|
-
forward_date?: unknown;
|
|
54
|
-
via_bot?: unknown;
|
|
55
|
-
sender_chat?: unknown;
|
|
56
|
-
caption?: string;
|
|
57
|
-
};
|
|
40
|
+
message: TelegramMessage;
|
|
58
41
|
/** Queue one reply for after the update's transaction commits. */
|
|
59
42
|
say: (chatId: string, text: string, keyboard?: InlineButton[][]) => void;
|
|
60
43
|
};
|
package/dist/telegram.d.ts
CHANGED
|
@@ -37,7 +37,7 @@ export declare function telegramHookSecret(dir: string, make?: boolean): string
|
|
|
37
37
|
export declare function telegramPushUrl(hooksBase: string | null): string | null;
|
|
38
38
|
/** A push is Telegram's when its secret header matches ours (compared in constant time). */
|
|
39
39
|
export declare function pushedByTelegram(header: unknown, secret: string | null): boolean;
|
|
40
|
-
/** Keep one pushed update for the bridge
|
|
40
|
+
/** Keep one pushed update for the bridge. A schema-invalid JSON update is logged and acknowledged, never retried. */
|
|
41
41
|
export declare function keepPushedUpdate(store: Store, botId: string, body: Buffer, now: Date): {
|
|
42
42
|
ok: true;
|
|
43
43
|
kept: boolean;
|
package/dist/telegram.js
CHANGED
|
@@ -46,6 +46,7 @@ import { phoneCommand, phoneStatus, phoneTaskView, PHONE_CONSOLE_FOOTER, PHONE_H
|
|
|
46
46
|
import { MATE_MESSAGE_MAX_CHARS } from "./mate.js";
|
|
47
47
|
import { envValue } from "./names.js";
|
|
48
48
|
import { applyProposalTap, processTelegramConversations, phoneLinkButton, replyContextFor, telegramConversationRepos, telegramRequestId, tooLongText, whichTaskText, } from "./telegram-mate.js";
|
|
49
|
+
import { askOf, parseTelegramUpdate, pickOf, readTelegramButtonData, readTelegramUpdate, telegramButton } from "./contracts/telegram-callback.js";
|
|
49
50
|
/** The environment name — and therefore the name the builder strips from agents (both names; see names.ts). */
|
|
50
51
|
export { TELEGRAM_TOKEN_ENV as TOKEN_ENV, TELEGRAM_TOKEN_ENVS as TOKEN_ENVS } from "./names.js";
|
|
51
52
|
/** BotFather's shape: numeric bot id, colon, secret. */
|
|
@@ -99,19 +100,21 @@ export function pushedByTelegram(header, secret) {
|
|
|
99
100
|
const given = Buffer.from(header), wanted = Buffer.from(secret);
|
|
100
101
|
return given.length === wanted.length && timingSafeEqual(given, wanted);
|
|
101
102
|
}
|
|
102
|
-
/** Keep one pushed update for the bridge
|
|
103
|
+
/** Keep one pushed update for the bridge. A schema-invalid JSON update is logged and acknowledged, never retried. */
|
|
103
104
|
export function keepPushedUpdate(store, botId, body, now) {
|
|
104
|
-
let
|
|
105
|
+
let raw;
|
|
105
106
|
try {
|
|
106
|
-
|
|
107
|
+
raw = JSON.parse(body.toString("utf8"));
|
|
107
108
|
}
|
|
108
109
|
catch {
|
|
109
110
|
return { ok: false };
|
|
110
111
|
}
|
|
111
|
-
const
|
|
112
|
-
if (update
|
|
113
|
-
|
|
114
|
-
|
|
112
|
+
const update = readTelegramUpdate(raw);
|
|
113
|
+
if (!update.ok) {
|
|
114
|
+
console.warn(`Ignoring a pushed Telegram update: ${update.issues.map(issue => issue.line).join("; ")}`);
|
|
115
|
+
return { ok: true, kept: false };
|
|
116
|
+
}
|
|
117
|
+
return { ok: true, kept: store.queueTelegramUpdate(botId, update.value.update_id, JSON.stringify(raw), now) };
|
|
115
118
|
}
|
|
116
119
|
/**
|
|
117
120
|
* Environment wins, the credential file beside the database otherwise.
|
|
@@ -623,7 +626,7 @@ function decideKeyboard(phoneOrigin, rows) {
|
|
|
623
626
|
catch {
|
|
624
627
|
origin = null;
|
|
625
628
|
}
|
|
626
|
-
return rows.map(row => row.flatMap((one) => "token" in one ? [
|
|
629
|
+
return rows.map(row => row.flatMap((one) => "token" in one ? [telegramButton(one.label, one.token)]
|
|
627
630
|
: phoneLinkButton(origin, one.link) ?? [])).filter(row => row.length > 0);
|
|
628
631
|
}
|
|
629
632
|
/** What this card may act on in the chat now, for this person under their current ceiling; null keeps its link. */
|
|
@@ -1311,10 +1314,7 @@ async function deliverOne(store, botId, binding, sender, notification, clock, ph
|
|
|
1311
1314
|
}, clock());
|
|
1312
1315
|
}
|
|
1313
1316
|
const keyboard = tokens.map(({ option, token }) => [
|
|
1314
|
-
{
|
|
1315
|
-
text: `${option.label}${option.id === decision.recommendation ? " ✓" : ""}${option.reversible ? "" : " ⚠"}`,
|
|
1316
|
-
callback_data: token,
|
|
1317
|
-
},
|
|
1317
|
+
telegramButton(`${option.label}${option.id === decision.recommendation ? " ✓" : ""}${option.reversible ? "" : " ⚠"}`, token),
|
|
1318
1318
|
]);
|
|
1319
1319
|
const last = parts[parts.length - 1];
|
|
1320
1320
|
const sent = await sender(last, keyboard);
|
|
@@ -1433,12 +1433,22 @@ async function drainUpdates(store, botId, transport, owner, generation, cursor,
|
|
|
1433
1433
|
report.problems.push(`getUpdates: ${said}`);
|
|
1434
1434
|
return;
|
|
1435
1435
|
}
|
|
1436
|
-
const updates = answer.result
|
|
1436
|
+
const updates = Array.isArray(answer.result) ? answer.result : [];
|
|
1437
1437
|
if (updates.length === 0)
|
|
1438
1438
|
return;
|
|
1439
|
-
for (const
|
|
1440
|
-
|
|
1441
|
-
|
|
1439
|
+
for (const raw of updates) {
|
|
1440
|
+
const update = readTelegramUpdate(raw);
|
|
1441
|
+
if (!update.ok) {
|
|
1442
|
+
// Telegram's own update in a shape this bridge doesn't read: said, and passed over so the next one is read.
|
|
1443
|
+
const id = raw?.update_id;
|
|
1444
|
+
report.problems.push(`an update Telegram sent couldn't be read: ${update.issues.map(issue => issue.line).join("; ")}`);
|
|
1445
|
+
if (typeof id !== "number" || !Number.isSafeInteger(id))
|
|
1446
|
+
return;
|
|
1447
|
+
offset = id + 1;
|
|
1448
|
+
continue;
|
|
1449
|
+
}
|
|
1450
|
+
await processUpdate(context, update.value, owner, generation);
|
|
1451
|
+
offset = update.value.update_id + 1;
|
|
1442
1452
|
}
|
|
1443
1453
|
}
|
|
1444
1454
|
// The budget ran out with Telegram still holding pages: said, not hidden.
|
|
@@ -1473,15 +1483,11 @@ async function processUpdate(context, update, owner, generation) {
|
|
|
1473
1483
|
async function drainInbox(context, owner, generation) {
|
|
1474
1484
|
let applied = 0;
|
|
1475
1485
|
for (const queued of context.store.telegramInbox(context.botId, PAGE_BUDGET * 100)) {
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
update
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
update = null;
|
|
1482
|
-
}
|
|
1483
|
-
if (update !== null && update.update_id === queued.updateId)
|
|
1484
|
-
await processUpdate(context, update, owner, generation);
|
|
1486
|
+
const update = parseTelegramUpdate(queued.payload);
|
|
1487
|
+
if (update.ok && update.value.update_id === queued.updateId)
|
|
1488
|
+
await processUpdate(context, update.value, owner, generation);
|
|
1489
|
+
else if (!update.ok)
|
|
1490
|
+
context.report.problems.push(`a pushed update couldn't be read: ${update.issues.map(issue => issue.line).join("; ")}`);
|
|
1485
1491
|
context.store.dropTelegramInbox(queued.updateId);
|
|
1486
1492
|
applied++;
|
|
1487
1493
|
}
|
|
@@ -1843,10 +1849,10 @@ function pickKeyboard(store, choices, focused) {
|
|
|
1843
1849
|
for (const one of choices) {
|
|
1844
1850
|
const ref = store.lookupRef(one.id);
|
|
1845
1851
|
if (ref !== null)
|
|
1846
|
-
rows.push([
|
|
1852
|
+
rows.push([telegramButton(`${one.title} · ${one.label}`.slice(0, 60), `pick:${ref.id}`)]);
|
|
1847
1853
|
}
|
|
1848
1854
|
if (focused)
|
|
1849
|
-
rows.push([
|
|
1855
|
+
rows.push([telegramButton("Back to the lead", "pick:lead")]);
|
|
1850
1856
|
return rows;
|
|
1851
1857
|
}
|
|
1852
1858
|
/** The title of the task this Telegram chat chose to talk about, if any. */
|
|
@@ -2106,23 +2112,30 @@ function applyCallback(context, update, effects) {
|
|
|
2106
2112
|
report.ignored++;
|
|
2107
2113
|
return;
|
|
2108
2114
|
}
|
|
2115
|
+
// The paired person, in their chat: a button whose data isn't one Toolroll makes is answered with why, and does nothing.
|
|
2116
|
+
const data = readTelegramButtonData(callback.data);
|
|
2117
|
+
if (!data.ok) {
|
|
2118
|
+
report.ignored++;
|
|
2119
|
+
ack(`That button couldn't be read (${data.issues.map(issue => issue.line).join("; ")}). Nothing was done.`.slice(0, 190));
|
|
2120
|
+
return;
|
|
2121
|
+
}
|
|
2109
2122
|
// A task picked from /tasks: this private chat now talks about it (or,
|
|
2110
2123
|
// "Back to the lead", about everything again). The task is re-proved
|
|
2111
2124
|
// against the chat's ceiling at the tap.
|
|
2112
|
-
|
|
2125
|
+
const pick = pickOf(token);
|
|
2126
|
+
if (pick !== null) {
|
|
2113
2127
|
if (tapChat !== binding.chatId) {
|
|
2114
2128
|
report.ignored++;
|
|
2115
2129
|
return;
|
|
2116
2130
|
}
|
|
2117
|
-
if (
|
|
2131
|
+
if (pick.ref === null) {
|
|
2118
2132
|
store.setChatFocus("telegram", binding.id, null, clock());
|
|
2119
2133
|
store.recordTelegramTaskMessage(binding, String(message.message_id), null, null, clock());
|
|
2120
2134
|
ack("Back to the lead");
|
|
2121
2135
|
editText(PHONE_BACK_TO_LEAD);
|
|
2122
2136
|
return;
|
|
2123
2137
|
}
|
|
2124
|
-
const
|
|
2125
|
-
const taskId = refId === undefined ? null : store.externalIdFor(Number(refId));
|
|
2138
|
+
const taskId = store.externalIdFor(pick.ref);
|
|
2126
2139
|
const repos = context.projects === null ? null : telegramConversationRepos(store, binding.approver, context.projects);
|
|
2127
2140
|
if (taskId === null || repos === null || !taskInCeiling(store, taskId, repos)) {
|
|
2128
2141
|
ack("That task isn't available here now.");
|
|
@@ -2136,7 +2149,7 @@ function applyCallback(context, update, effects) {
|
|
|
2136
2149
|
const current = store.taskFamilyOf(taskId, repos, false)?.current.id ?? id;
|
|
2137
2150
|
const view = phoneTaskView(store, repos, current, clock());
|
|
2138
2151
|
store.recordTelegramTaskMessage(binding, String(message.message_id), current, view.run, clock());
|
|
2139
|
-
editText(phoneFocusText(view.text), [[
|
|
2152
|
+
editText(phoneFocusText(view.text), [[telegramButton("Back to the lead", "pick:lead")]]);
|
|
2140
2153
|
return;
|
|
2141
2154
|
}
|
|
2142
2155
|
// A teammate's question (v93): an option answers it; "Answer in words" asks for a reply.
|
|
@@ -2206,13 +2219,13 @@ function applyCallback(context, update, effects) {
|
|
|
2206
2219
|
return;
|
|
2207
2220
|
}
|
|
2208
2221
|
// The lead's question to its owner: an option is sent as their next message; "Something else" asks them to type it.
|
|
2209
|
-
const askTap =
|
|
2222
|
+
const askTap = askOf(token);
|
|
2210
2223
|
if (askTap !== null) {
|
|
2211
2224
|
if (tapChat !== binding.chatId || context.conversation === undefined) {
|
|
2212
2225
|
report.ignored++;
|
|
2213
2226
|
return;
|
|
2214
2227
|
}
|
|
2215
|
-
const turn =
|
|
2228
|
+
const turn = askTap.turn;
|
|
2216
2229
|
const found = store.getMateTurn(turn)?.approver === binding.approver ? store.mateAskState(turn, clock()) : { state: "expired" };
|
|
2217
2230
|
if (found.state !== "open") {
|
|
2218
2231
|
const line = found.state === "answered" ? "That question was already answered." : "That question expired. Send your answer as a message.";
|
|
@@ -2225,11 +2238,11 @@ function applyCallback(context, update, effects) {
|
|
|
2225
2238
|
ack("Your answer is on its way.");
|
|
2226
2239
|
return;
|
|
2227
2240
|
}
|
|
2228
|
-
if (askTap
|
|
2241
|
+
if (askTap.option === "x") {
|
|
2229
2242
|
ack("Type your answer as a message.");
|
|
2230
2243
|
return;
|
|
2231
2244
|
}
|
|
2232
|
-
const option = ask.options[
|
|
2245
|
+
const option = ask.options[askTap.option];
|
|
2233
2246
|
if (option === undefined) {
|
|
2234
2247
|
ack("That option is no longer there.");
|
|
2235
2248
|
return;
|
|
@@ -2370,8 +2383,8 @@ function applyCallback(context, update, effects) {
|
|
|
2370
2383
|
store.createTelegramAction({ token: cancel, binding: binding.id, decision: decision.id, optionId: option.id, phase: "cancel", chatId: binding.chatId, messageId: placedOn, ttlMs: CONFIRM_TTL_MS }, clock());
|
|
2371
2384
|
ack("irreversible — confirm it");
|
|
2372
2385
|
editText(`⚠ ${option.label} is IRREVERSIBLE.\n${option.consequence}\n${draft === null ? "" : `\nWith your note:\n${draft.note.split("\n").map(line => `| ${line}`).join("\n")}\n`}\nConfirm?`, [
|
|
2373
|
-
[
|
|
2374
|
-
[
|
|
2386
|
+
[telegramButton(`⚠ Yes, ${option.label}`, confirm)],
|
|
2387
|
+
[telegramButton("Cancel", cancel)],
|
|
2375
2388
|
]);
|
|
2376
2389
|
return;
|
|
2377
2390
|
}
|
|
@@ -2418,10 +2431,7 @@ function applyCallback(context, update, effects) {
|
|
|
2418
2431
|
}
|
|
2419
2432
|
ack("cancelled");
|
|
2420
2433
|
editText(`Q: ${decision.question}`, fresh.map(({ option, token: choose }) => [
|
|
2421
|
-
{
|
|
2422
|
-
text: `${option.label}${option.id === decision.recommendation ? " ✓" : ""}${option.reversible ? "" : " ⚠"}`,
|
|
2423
|
-
callback_data: choose,
|
|
2424
|
-
},
|
|
2434
|
+
telegramButton(`${option.label}${option.id === decision.recommendation ? " ✓" : ""}${option.reversible ? "" : " ⚠"}`, choose),
|
|
2425
2435
|
]));
|
|
2426
2436
|
}
|
|
2427
2437
|
function answerNow(context, decision, choice, binding, ack, editText) {
|
package/dist/text-limits.d.ts
CHANGED
|
@@ -79,6 +79,18 @@ export declare const TEXT_LIMITS: {
|
|
|
79
79
|
readonly flowScriptInline: 1600;
|
|
80
80
|
/** A research report's summary, in UTF-8 bytes. */
|
|
81
81
|
readonly reportSummary: 2500;
|
|
82
|
+
/** A scout's whole report file (src/contracts/scout-report.ts), in UTF-8 bytes. */
|
|
83
|
+
readonly reportPayloadBytes: number;
|
|
84
|
+
/** A report's document (markdown), in UTF-8 bytes. */
|
|
85
|
+
readonly reportDocumentBytes: number;
|
|
86
|
+
/** A report's title, and a follow-up's or an item's title, in UTF-8 bytes. */
|
|
87
|
+
readonly reportTitleBytes: 200;
|
|
88
|
+
/** Why an item fits, in UTF-8 bytes. */
|
|
89
|
+
readonly reportWhyBytes: 1000;
|
|
90
|
+
/** A web address a report cites, in UTF-8 bytes. */
|
|
91
|
+
readonly reportUrlBytes: 2000;
|
|
92
|
+
/** A screenshot's caption and its file name, in UTF-8 bytes. */
|
|
93
|
+
readonly reportCaptionBytes: 300;
|
|
82
94
|
/** What one flow step passes on to the steps after it. */
|
|
83
95
|
readonly stageOutput: 12000;
|
|
84
96
|
/** The planner's whole handoff file, in UTF-8 bytes. */
|
|
@@ -91,6 +103,10 @@ export declare const TEXT_LIMITS: {
|
|
|
91
103
|
readonly planItem: 600;
|
|
92
104
|
/** One path a plan expects to touch. */
|
|
93
105
|
readonly planTouch: 200;
|
|
106
|
+
/** How many paths a task's scope may say it touches (a plan says at most 32 of them). A count, not a length. */
|
|
107
|
+
readonly scopeTouches: 50;
|
|
108
|
+
/** Why a task was sized as it was, as its sealed route keeps it. */
|
|
109
|
+
readonly sizeReason: 300;
|
|
94
110
|
/** A planner's amendment note: why the filed contract must change. */
|
|
95
111
|
readonly planAmendment: 1000;
|
|
96
112
|
/** An acceptance criterion's id, statement and advisory how, in UTF-8 bytes. */
|
|
@@ -106,6 +122,131 @@ export declare const TEXT_LIMITS: {
|
|
|
106
122
|
/** One proof line — a criterion statement, evidence ref, check command or summary, changed path, caveat, or
|
|
107
123
|
* screenshot path or caption — in UTF-8 bytes. */
|
|
108
124
|
readonly proofLineBytes: 300;
|
|
125
|
+
/** The task sizing classifier's reason (src/contracts/task-sizing.ts). */
|
|
126
|
+
readonly sizingReason: 160;
|
|
127
|
+
/** A review comment's or build-review finding's path, and its note or failure scenario (src/contracts/review-findings.ts). */
|
|
128
|
+
readonly reviewPath: 300;
|
|
129
|
+
readonly reviewNote: 500;
|
|
130
|
+
/** A parked decision (src/contracts/decision.ts): its recap and question, an option's id, label and consequence, and who it is for. */
|
|
131
|
+
readonly decisionRecap: 2000;
|
|
132
|
+
readonly decisionQuestion: 2000;
|
|
133
|
+
readonly decisionOptionId: 40;
|
|
134
|
+
/** A decision's recommendation: an option's id, optionally followed by ": " and why. */
|
|
135
|
+
readonly decisionRecommendation: 500;
|
|
136
|
+
readonly decisionLabel: 120;
|
|
137
|
+
readonly decisionConsequence: 500;
|
|
138
|
+
readonly decisionAssignee: 120;
|
|
139
|
+
/** A teammate's turn (src/contracts/teammate-turn.ts): the answer it picks (and each option it offers), its question, its reason and what it remembers. */
|
|
140
|
+
readonly teammateAnswer: 60;
|
|
141
|
+
readonly teammateQuestion: 600;
|
|
142
|
+
readonly teammateReason: 400;
|
|
143
|
+
readonly teammateRemember: 300;
|
|
144
|
+
/** The lead's tools and the MCP gateway (src/contracts/lead-tools.ts, gateway-tools.ts): a task's id as a tool names
|
|
145
|
+
* it, a task's title and one path it touches, and a project's path as the gateway names it (an assignment brief or
|
|
146
|
+
* project context, and the rest of the gateway). */
|
|
147
|
+
readonly taskRef: 64;
|
|
148
|
+
readonly taskTitle: 200;
|
|
149
|
+
readonly taskTouch: 200;
|
|
150
|
+
readonly projectPath: 4096;
|
|
151
|
+
readonly gatewayRepo: 800;
|
|
152
|
+
/** A project-context query, a check-log search, a memory search, a task search and a changed file's path. */
|
|
153
|
+
readonly contextQuery: 1000;
|
|
154
|
+
readonly logSearch: 120;
|
|
155
|
+
readonly memorySearch: 300;
|
|
156
|
+
readonly taskSearch: 200;
|
|
157
|
+
readonly diffPath: 300;
|
|
158
|
+
/** A hold's or cancel's reason, an answer's rationale and option, a worker's name, an agent change's reason, a
|
|
159
|
+
* provider and model name, how a task's checks were asked for, and an ISO time a recap counts from. */
|
|
160
|
+
readonly proposalReason: 200;
|
|
161
|
+
readonly answerRationale: 400;
|
|
162
|
+
readonly answerOption: 64;
|
|
163
|
+
readonly workerName: 60;
|
|
164
|
+
readonly agentWhy: 400;
|
|
165
|
+
readonly agentProvider: 20;
|
|
166
|
+
readonly agentModel: 120;
|
|
167
|
+
readonly checksWords: 80;
|
|
168
|
+
readonly recapSince: 30;
|
|
169
|
+
/** A shared action's fields as the lead proposes them (propose_action). */
|
|
170
|
+
readonly actionSample: 800;
|
|
171
|
+
readonly actionContent: 12000;
|
|
172
|
+
readonly actionTitle: 120;
|
|
173
|
+
readonly actionName: 40;
|
|
174
|
+
readonly actionCommand: 400;
|
|
175
|
+
readonly actionUrl: 500;
|
|
176
|
+
readonly actionSecret: 64;
|
|
177
|
+
readonly actionAbout: 240;
|
|
178
|
+
/** A teammate change (propose_teammate): a soul section's title, a routine's schedule, a tool, an action, a limit's
|
|
179
|
+
* field, a name, a soul file, a note, a choice and text. */
|
|
180
|
+
readonly teammateSection: 60;
|
|
181
|
+
readonly teammateSchedule: 80;
|
|
182
|
+
readonly teammateTool: 40;
|
|
183
|
+
readonly teammateAction: 64;
|
|
184
|
+
readonly teammateName: 40;
|
|
185
|
+
readonly teammateSoul: 12000;
|
|
186
|
+
readonly teammateNote: 300;
|
|
187
|
+
readonly teammateChoice: 60;
|
|
188
|
+
readonly teammateText: 2000;
|
|
189
|
+
/** A project knowledge reference id, a promise and why it is released, what the lead remembers (its text, a
|
|
190
|
+
* decision's reason and source), a person's name, and a question to the owner with its options. */
|
|
191
|
+
readonly knowledgeReference: 20;
|
|
192
|
+
readonly promise: 240;
|
|
193
|
+
readonly rememberText: 240;
|
|
194
|
+
readonly rememberWhy: 2000;
|
|
195
|
+
readonly rememberSource: 200;
|
|
196
|
+
readonly personName: 80;
|
|
197
|
+
readonly ownerQuestion: 200;
|
|
198
|
+
readonly ownerOption: 40;
|
|
199
|
+
/** A gateway filing's idempotency key. */
|
|
200
|
+
readonly idempotencyKey: 64;
|
|
201
|
+
/** The lead's catch-up bundle (src/contracts/lead-context.ts), in UTF-8 bytes, and the lines it clips: an open promise,
|
|
202
|
+
* a confirmed correction, the end of changed instructions a correction shows, and what an open proposal is about. */
|
|
203
|
+
readonly leadContextBytes: 8000;
|
|
204
|
+
readonly leadPromise: 160;
|
|
205
|
+
readonly leadCorrection: 300;
|
|
206
|
+
readonly leadCorrectionInstructions: 240;
|
|
207
|
+
readonly leadProposalAbout: 120;
|
|
208
|
+
/** Project knowledge (src/contracts/project-knowledge.ts), in UTF-8 bytes: the instructions (also the memory pass's
|
|
209
|
+
* budget for them), a reference's title, path and text, the context a run gets, the decision lines in it, and the
|
|
210
|
+
* repository excerpts added when at least the minimum is left. */
|
|
211
|
+
readonly knowledgeInstructionsBytes: 4000;
|
|
212
|
+
readonly knowledgeTitleBytes: 120;
|
|
213
|
+
readonly knowledgePathBytes: 300;
|
|
214
|
+
readonly knowledgeReferenceBytes: 12000;
|
|
215
|
+
readonly knowledgeContextBytes: 24000;
|
|
216
|
+
readonly knowledgeDecisionsBytes: 1500;
|
|
217
|
+
readonly knowledgeRepositoryBytes: 6000;
|
|
218
|
+
readonly knowledgeRepositoryMinBytes: 3000;
|
|
219
|
+
/** A project decision (src/contracts/project-memory.ts), in UTF-8 bytes: the choice, why, who decided, where it came
|
|
220
|
+
* from, and why it was retired. */
|
|
221
|
+
readonly decisionClaimBytes: 240;
|
|
222
|
+
readonly decisionWhyBytes: 2000;
|
|
223
|
+
readonly decisionByBytes: 80;
|
|
224
|
+
readonly decisionSourceBytes: 200;
|
|
225
|
+
readonly decisionRetireBytes: 500;
|
|
226
|
+
/** A skill package (src/contracts/project-skills.ts): its name, description, requirements and source in UTF-8 bytes,
|
|
227
|
+
* a file's path, SKILL.md, one file, the package and the enabled selection in bytes; a test's sample request and
|
|
228
|
+
* feedback in characters and bytes. */
|
|
229
|
+
readonly skillNameBytes: 64;
|
|
230
|
+
readonly skillDescriptionBytes: 1024;
|
|
231
|
+
readonly skillRequirementsBytes: 500;
|
|
232
|
+
readonly skillSourceBytes: 500;
|
|
233
|
+
readonly skillPath: 240;
|
|
234
|
+
readonly skillBodyBytes: number;
|
|
235
|
+
readonly skillFileBytes: number;
|
|
236
|
+
readonly skillPackageBytes: number;
|
|
237
|
+
readonly skillSelectionBytes: number;
|
|
238
|
+
readonly skillSample: 800;
|
|
239
|
+
readonly skillSampleBytes: 4000;
|
|
240
|
+
readonly skillFeedback: 500;
|
|
241
|
+
readonly skillFeedbackBytes: 2000;
|
|
242
|
+
/** The memory pass (src/contracts/memory-pass.ts): one session's trace, and in its verdict an effect, a mistake and
|
|
243
|
+
* the instruction it proposes. */
|
|
244
|
+
readonly memoryTrace: 40000;
|
|
245
|
+
readonly memoryEffect: 300;
|
|
246
|
+
readonly memoryMistake: 300;
|
|
247
|
+
readonly memoryInstruction: 240;
|
|
248
|
+
/** A Telegram button's callback_data, in UTF-8 bytes: Telegram refuses a button with more. */
|
|
249
|
+
readonly telegramCallbackDataBytes: 64;
|
|
109
250
|
};
|
|
110
251
|
export type TextLimitKey = keyof typeof TEXT_LIMITS;
|
|
111
252
|
/** One chat message on each platform. Longer text is split across messages, never cut. Teams: the text one Adaptive Card
|
|
@@ -118,7 +259,7 @@ export declare const PLATFORM_LIMITS: {
|
|
|
118
259
|
};
|
|
119
260
|
export type Platform = keyof typeof PLATFORM_LIMITS;
|
|
120
261
|
/** The line a model reads before it writes a field with a limit. */
|
|
121
|
-
export declare function limitRule(what: string, limit: number, unit?: "characters" | "bytes"): string;
|
|
262
|
+
export declare function limitRule(what: string, limit: number, unit?: "characters" | "bytes", shorten?: boolean): string;
|
|
122
263
|
/** One field over its limit: what it is, its limit, and how long it came back. */
|
|
123
264
|
export type Overrun = {
|
|
124
265
|
field: string;
|
package/dist/text-limits.js
CHANGED
|
@@ -79,6 +79,18 @@ export const TEXT_LIMITS = {
|
|
|
79
79
|
flowScriptInline: 1_600,
|
|
80
80
|
/** A research report's summary, in UTF-8 bytes. */
|
|
81
81
|
reportSummary: 2_500,
|
|
82
|
+
/** A scout's whole report file (src/contracts/scout-report.ts), in UTF-8 bytes. */
|
|
83
|
+
reportPayloadBytes: 96 * 1024,
|
|
84
|
+
/** A report's document (markdown), in UTF-8 bytes. */
|
|
85
|
+
reportDocumentBytes: 64 * 1024,
|
|
86
|
+
/** A report's title, and a follow-up's or an item's title, in UTF-8 bytes. */
|
|
87
|
+
reportTitleBytes: 200,
|
|
88
|
+
/** Why an item fits, in UTF-8 bytes. */
|
|
89
|
+
reportWhyBytes: 1_000,
|
|
90
|
+
/** A web address a report cites, in UTF-8 bytes. */
|
|
91
|
+
reportUrlBytes: 2_000,
|
|
92
|
+
/** A screenshot's caption and its file name, in UTF-8 bytes. */
|
|
93
|
+
reportCaptionBytes: 300,
|
|
82
94
|
/** What one flow step passes on to the steps after it. */
|
|
83
95
|
stageOutput: 12_000,
|
|
84
96
|
/** The planner's whole handoff file, in UTF-8 bytes. */
|
|
@@ -91,6 +103,10 @@ export const TEXT_LIMITS = {
|
|
|
91
103
|
planItem: 600,
|
|
92
104
|
/** One path a plan expects to touch. */
|
|
93
105
|
planTouch: 200,
|
|
106
|
+
/** How many paths a task's scope may say it touches (a plan says at most 32 of them). A count, not a length. */
|
|
107
|
+
scopeTouches: 50,
|
|
108
|
+
/** Why a task was sized as it was, as its sealed route keeps it. */
|
|
109
|
+
sizeReason: 300,
|
|
94
110
|
/** A planner's amendment note: why the filed contract must change. */
|
|
95
111
|
planAmendment: 1_000,
|
|
96
112
|
/** An acceptance criterion's id, statement and advisory how, in UTF-8 bytes. */
|
|
@@ -106,13 +122,140 @@ export const TEXT_LIMITS = {
|
|
|
106
122
|
/** One proof line — a criterion statement, evidence ref, check command or summary, changed path, caveat, or
|
|
107
123
|
* screenshot path or caption — in UTF-8 bytes. */
|
|
108
124
|
proofLineBytes: 300,
|
|
125
|
+
/** The task sizing classifier's reason (src/contracts/task-sizing.ts). */
|
|
126
|
+
sizingReason: 160,
|
|
127
|
+
/** A review comment's or build-review finding's path, and its note or failure scenario (src/contracts/review-findings.ts). */
|
|
128
|
+
reviewPath: 300,
|
|
129
|
+
reviewNote: 500,
|
|
130
|
+
/** A parked decision (src/contracts/decision.ts): its recap and question, an option's id, label and consequence, and who it is for. */
|
|
131
|
+
decisionRecap: 2_000,
|
|
132
|
+
decisionQuestion: 2_000,
|
|
133
|
+
decisionOptionId: 40,
|
|
134
|
+
/** A decision's recommendation: an option's id, optionally followed by ": " and why. */
|
|
135
|
+
decisionRecommendation: 500,
|
|
136
|
+
decisionLabel: 120,
|
|
137
|
+
decisionConsequence: 500,
|
|
138
|
+
decisionAssignee: 120,
|
|
139
|
+
/** A teammate's turn (src/contracts/teammate-turn.ts): the answer it picks (and each option it offers), its question, its reason and what it remembers. */
|
|
140
|
+
teammateAnswer: 60,
|
|
141
|
+
teammateQuestion: 600,
|
|
142
|
+
teammateReason: 400,
|
|
143
|
+
teammateRemember: 300,
|
|
144
|
+
/** The lead's tools and the MCP gateway (src/contracts/lead-tools.ts, gateway-tools.ts): a task's id as a tool names
|
|
145
|
+
* it, a task's title and one path it touches, and a project's path as the gateway names it (an assignment brief or
|
|
146
|
+
* project context, and the rest of the gateway). */
|
|
147
|
+
taskRef: 64,
|
|
148
|
+
taskTitle: 200,
|
|
149
|
+
taskTouch: 200,
|
|
150
|
+
projectPath: 4_096,
|
|
151
|
+
gatewayRepo: 800,
|
|
152
|
+
/** A project-context query, a check-log search, a memory search, a task search and a changed file's path. */
|
|
153
|
+
contextQuery: 1_000,
|
|
154
|
+
logSearch: 120,
|
|
155
|
+
memorySearch: 300,
|
|
156
|
+
taskSearch: 200,
|
|
157
|
+
diffPath: 300,
|
|
158
|
+
/** A hold's or cancel's reason, an answer's rationale and option, a worker's name, an agent change's reason, a
|
|
159
|
+
* provider and model name, how a task's checks were asked for, and an ISO time a recap counts from. */
|
|
160
|
+
proposalReason: 200,
|
|
161
|
+
answerRationale: 400,
|
|
162
|
+
answerOption: 64,
|
|
163
|
+
workerName: 60,
|
|
164
|
+
agentWhy: 400,
|
|
165
|
+
agentProvider: 20,
|
|
166
|
+
agentModel: 120,
|
|
167
|
+
checksWords: 80,
|
|
168
|
+
recapSince: 30,
|
|
169
|
+
/** A shared action's fields as the lead proposes them (propose_action). */
|
|
170
|
+
actionSample: 800,
|
|
171
|
+
actionContent: 12_000,
|
|
172
|
+
actionTitle: 120,
|
|
173
|
+
actionName: 40,
|
|
174
|
+
actionCommand: 400,
|
|
175
|
+
actionUrl: 500,
|
|
176
|
+
actionSecret: 64,
|
|
177
|
+
actionAbout: 240,
|
|
178
|
+
/** A teammate change (propose_teammate): a soul section's title, a routine's schedule, a tool, an action, a limit's
|
|
179
|
+
* field, a name, a soul file, a note, a choice and text. */
|
|
180
|
+
teammateSection: 60,
|
|
181
|
+
teammateSchedule: 80,
|
|
182
|
+
teammateTool: 40,
|
|
183
|
+
teammateAction: 64,
|
|
184
|
+
teammateName: 40,
|
|
185
|
+
teammateSoul: 12_000,
|
|
186
|
+
teammateNote: 300,
|
|
187
|
+
teammateChoice: 60,
|
|
188
|
+
teammateText: 2_000,
|
|
189
|
+
/** A project knowledge reference id, a promise and why it is released, what the lead remembers (its text, a
|
|
190
|
+
* decision's reason and source), a person's name, and a question to the owner with its options. */
|
|
191
|
+
knowledgeReference: 20,
|
|
192
|
+
promise: 240,
|
|
193
|
+
rememberText: 240,
|
|
194
|
+
rememberWhy: 2_000,
|
|
195
|
+
rememberSource: 200,
|
|
196
|
+
personName: 80,
|
|
197
|
+
ownerQuestion: 200,
|
|
198
|
+
ownerOption: 40,
|
|
199
|
+
/** A gateway filing's idempotency key. */
|
|
200
|
+
idempotencyKey: 64,
|
|
201
|
+
/** The lead's catch-up bundle (src/contracts/lead-context.ts), in UTF-8 bytes, and the lines it clips: an open promise,
|
|
202
|
+
* a confirmed correction, the end of changed instructions a correction shows, and what an open proposal is about. */
|
|
203
|
+
leadContextBytes: 8_000,
|
|
204
|
+
leadPromise: 160,
|
|
205
|
+
leadCorrection: 300,
|
|
206
|
+
leadCorrectionInstructions: 240,
|
|
207
|
+
leadProposalAbout: 120,
|
|
208
|
+
/** Project knowledge (src/contracts/project-knowledge.ts), in UTF-8 bytes: the instructions (also the memory pass's
|
|
209
|
+
* budget for them), a reference's title, path and text, the context a run gets, the decision lines in it, and the
|
|
210
|
+
* repository excerpts added when at least the minimum is left. */
|
|
211
|
+
knowledgeInstructionsBytes: 4_000,
|
|
212
|
+
knowledgeTitleBytes: 120,
|
|
213
|
+
knowledgePathBytes: 300,
|
|
214
|
+
knowledgeReferenceBytes: 12_000,
|
|
215
|
+
knowledgeContextBytes: 24_000,
|
|
216
|
+
knowledgeDecisionsBytes: 1_500,
|
|
217
|
+
knowledgeRepositoryBytes: 6_000,
|
|
218
|
+
knowledgeRepositoryMinBytes: 3_000,
|
|
219
|
+
/** A project decision (src/contracts/project-memory.ts), in UTF-8 bytes: the choice, why, who decided, where it came
|
|
220
|
+
* from, and why it was retired. */
|
|
221
|
+
decisionClaimBytes: 240,
|
|
222
|
+
decisionWhyBytes: 2_000,
|
|
223
|
+
decisionByBytes: 80,
|
|
224
|
+
decisionSourceBytes: 200,
|
|
225
|
+
decisionRetireBytes: 500,
|
|
226
|
+
/** A skill package (src/contracts/project-skills.ts): its name, description, requirements and source in UTF-8 bytes,
|
|
227
|
+
* a file's path, SKILL.md, one file, the package and the enabled selection in bytes; a test's sample request and
|
|
228
|
+
* feedback in characters and bytes. */
|
|
229
|
+
skillNameBytes: 64,
|
|
230
|
+
skillDescriptionBytes: 1_024,
|
|
231
|
+
skillRequirementsBytes: 500,
|
|
232
|
+
skillSourceBytes: 500,
|
|
233
|
+
skillPath: 240,
|
|
234
|
+
skillBodyBytes: 24 * 1024,
|
|
235
|
+
skillFileBytes: 256 * 1024,
|
|
236
|
+
skillPackageBytes: 1024 * 1024,
|
|
237
|
+
skillSelectionBytes: 2 * 1024 * 1024,
|
|
238
|
+
skillSample: 800,
|
|
239
|
+
skillSampleBytes: 4_000,
|
|
240
|
+
skillFeedback: 500,
|
|
241
|
+
skillFeedbackBytes: 2_000,
|
|
242
|
+
/** The memory pass (src/contracts/memory-pass.ts): one session's trace, and in its verdict an effect, a mistake and
|
|
243
|
+
* the instruction it proposes. */
|
|
244
|
+
memoryTrace: 40_000,
|
|
245
|
+
memoryEffect: 300,
|
|
246
|
+
memoryMistake: 300,
|
|
247
|
+
memoryInstruction: 240,
|
|
248
|
+
/** A Telegram button's callback_data, in UTF-8 bytes: Telegram refuses a button with more. */
|
|
249
|
+
telegramCallbackDataBytes: 64,
|
|
109
250
|
};
|
|
110
251
|
/** One chat message on each platform. Longer text is split across messages, never cut. Teams: the text one Adaptive Card
|
|
111
252
|
* holds, well inside its 28 KB message. */
|
|
112
253
|
export const PLATFORM_LIMITS = { telegram: 4_096, discord: 2_000, slack: 4_000, teams: 6_000 };
|
|
113
254
|
const count = (n) => n.toLocaleString("en-US");
|
|
114
255
|
/** The line a model reads before it writes a field with a limit. */
|
|
115
|
-
export function limitRule(what, limit, unit = "characters") {
|
|
256
|
+
export function limitRule(what, limit, unit = "characters", shorten = true) {
|
|
257
|
+
if (!shorten)
|
|
258
|
+
return `${what}: at most ${count(limit)} ${unit}. Longer text is refused.`;
|
|
116
259
|
return `${what}: at most ${count(limit)} ${unit}. Put the most important part first. Longer text is not cut: you will be asked to shorten it.`;
|
|
117
260
|
}
|
|
118
261
|
/** How long a text is in a limit's unit. */
|
package/dist/tools-ui.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type FoundTool, type ProjectTool, type ToolSpec } from "./project-tools.js";
|
|
2
|
-
export declare const TOOLS_CSS = ".tools{max-width:780px;min-width:0;overflow-wrap:anywhere}.tools .card{padding:16px 18px;margin:12px 0;min-width:0}.tools .card h2{font-size:1.05rem;margin:0;color:var(--so-ink);font-weight:600}.tools .tool-heading{display:flex;align-items:center;gap:10px}.tools .tool-heading h2{flex:1;min-width:0}.tools .tool-state{font-size:.85rem;flex-shrink:0;color:var(--so-muted)}.tools .tool-state[data-ready=\"false\"]{color:var(--so-warning)}.tools .card>p{margin:6px 0 0}.tools code{white-space:pre-wrap;overflow-wrap:anywhere;word-break:break-word;font-size:.85rem}.tools form{display:grid;gap:10px;margin:0}.tools label{display:grid;gap:6px}.tools input,.tools select{box-sizing:border-box;width:100%;max-width:100%;min-width:0}.tools button{justify-self:start;white-space:nowrap;min-height:44px;max-width:100%;overflow:hidden;text-overflow:ellipsis}.tools details:not(.card){margin:6px 0 0;padding:0;border:0;border-radius:0;background:none;box-shadow:none}.tools details:not(.card)>summary{min-height:36px;display:flex;align-items:center;font-size:.9rem;color:var(--so-muted);cursor:pointer}.tools details:not(.card)[open]>summary{color:var(--so-ink)}.tools details.card>summary{cursor:pointer;min-height:44px;display:flex;align-items:center;font-weight:600}.tools summary{list-style:none;gap:10px}.tools summary::-webkit-details-marker{display:none}.tools summary::before{content:\"\";flex-shrink:0;width:6px;height:6px;margin:0 2px;border-right:1.5px solid currentColor;border-bottom:1.5px solid currentColor;transform:rotate(-45deg);transition:transform .15s}.tools details[open]>summary::before{transform:rotate(45deg)}.tools details:not(.card) form{padding:4px 0 10px}.tools .tool-facts{margin:0 0 8px;display:grid;gap:4px;font-size:.9rem}.tools .tool-facts p{margin:0}.tools .tool-controls{display:flex;gap:12px;flex-wrap:wrap;margin-top:12px}.tools .tool-found{display:flex;gap:10px;align-items:flex-start}.tools .tool-found input{flex:0 0 auto;width:18px;height:18px;margin-top:3px}.tools .tool-found span{min-width:0}.tools .problem{padding:10px 12px;margin:8px 0 0}.tools .tool-connect{scroll-margin-top:72px}.tools .connect-wanted{background:var(--so-accent);color:var(--so-on-accent);border-color:var(--so-accent)}.tools .connect-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(210px,1fr));gap:8px}.tools .connect-tile{display:grid;grid-template-columns:auto 1fr;column-gap:10px;align-items:center;justify-self:stretch;text-align:left;white-space:normal;padding:10px 12px;border:1px solid var(--so-line);border-radius:10px;background:var(--so-paper);color:var(--so-ink);min-height:60px;font:inherit;cursor:pointer;scroll-margin-top:96px}.tools .connect-tile:hover{border-color:var(--so-input-line);background:var(--so-raised)}.tools .connect-tile:target,.tools .connect-tile:focus-visible{outline:2px solid var(--so-accent);outline-offset:2px}.tools .connect-tile .brand-mark{grid-row:span 2}.tools .connect-tile strong{font-weight:600;line-height:1.3}.tools .connect-tile>span:not(.brand-mark){font-size:.8rem;color:var(--so-muted);line-height:1.35;overflow:hidden;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical}.tools .connect-tile[data-state=\"connected\"]>span:not(.brand-mark){color:var(--so-success)}.tools .connect-local{grid-column:1/-1}.tools .connect-local>span:not(.brand-mark){-webkit-line-clamp:unset}.tools .connect-problem{margin:0}.tools .connect-problem:focus{outline:2px solid var(--so-accent);outline-offset:2px}.tools .connect-tile:disabled{cursor:default;opacity:.6}@media(max-width:600px){.tools .connect-grid{grid-template-columns:1fr 1fr}.tools .connect-tile:not(.connect-local)>span:not(.brand-mark){display:none}.tools .connect-local>span:not(.brand-mark){grid-column:2}.tools .connect-tile{min-height:52px;padding:8px 10px}.tools .connect-tile .brand-mark{grid-row:auto}.tools input,.tools select{font-size:16px}.tools .card{padding:14px}}";
|
|
2
|
+
export declare const TOOLS_CSS = ".tools{max-width:780px;min-width:0;overflow-wrap:anywhere}.tools .card{padding:16px 18px;margin:12px 0;min-width:0}.tools .card h2{font-size:1.05rem;margin:0;color:var(--so-ink);font-weight:600}.tools .tool-heading{display:flex;align-items:center;gap:10px}.tools .tool-heading h2{flex:1;min-width:0}.tools .tool-state{font-size:.85rem;flex-shrink:0;color:var(--so-muted)}.tools .tool-state[data-ready=\"false\"]{color:var(--so-warning)}.tools .card>p{margin:6px 0 0}.tools .tool-note{color:var(--so-warning)}.tools code{white-space:pre-wrap;overflow-wrap:anywhere;word-break:break-word;font-size:.85rem}.tools form{display:grid;gap:10px;margin:0}.tools label{display:grid;gap:6px}.tools input,.tools select{box-sizing:border-box;width:100%;max-width:100%;min-width:0}.tools button{justify-self:start;white-space:nowrap;min-height:44px;max-width:100%;overflow:hidden;text-overflow:ellipsis}.tools details:not(.card){margin:6px 0 0;padding:0;border:0;border-radius:0;background:none;box-shadow:none}.tools details:not(.card)>summary{min-height:36px;display:flex;align-items:center;font-size:.9rem;color:var(--so-muted);cursor:pointer}.tools details:not(.card)[open]>summary{color:var(--so-ink)}.tools details.card>summary{cursor:pointer;min-height:44px;display:flex;align-items:center;font-weight:600}.tools summary{list-style:none;gap:10px}.tools summary::-webkit-details-marker{display:none}.tools summary::before{content:\"\";flex-shrink:0;width:6px;height:6px;margin:0 2px;border-right:1.5px solid currentColor;border-bottom:1.5px solid currentColor;transform:rotate(-45deg);transition:transform .15s}.tools details[open]>summary::before{transform:rotate(45deg)}.tools details:not(.card) form{padding:4px 0 10px}.tools .tool-facts{margin:0 0 8px;display:grid;gap:4px;font-size:.9rem}.tools .tool-facts p{margin:0}.tools .tool-controls{display:flex;gap:12px;flex-wrap:wrap;margin-top:12px}.tools .tool-found{display:flex;gap:10px;align-items:flex-start}.tools .tool-found input{flex:0 0 auto;width:18px;height:18px;margin-top:3px}.tools .tool-found span{min-width:0}.tools .problem{padding:10px 12px;margin:8px 0 0}.tools .tool-connect{scroll-margin-top:72px}.tools .connect-wanted{background:var(--so-accent);color:var(--so-on-accent);border-color:var(--so-accent)}.tools .connect-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(210px,1fr));gap:8px}.tools .connect-tile{display:grid;grid-template-columns:auto 1fr;column-gap:10px;align-items:center;justify-self:stretch;text-align:left;white-space:normal;padding:10px 12px;border:1px solid var(--so-line);border-radius:10px;background:var(--so-paper);color:var(--so-ink);min-height:60px;font:inherit;cursor:pointer;scroll-margin-top:96px}.tools .connect-tile:hover{border-color:var(--so-input-line);background:var(--so-raised)}.tools .connect-tile:target,.tools .connect-tile:focus-visible{outline:2px solid var(--so-accent);outline-offset:2px}.tools .connect-tile .brand-mark{grid-row:span 2}.tools .connect-tile strong{font-weight:600;line-height:1.3}.tools .connect-tile>span:not(.brand-mark){font-size:.8rem;color:var(--so-muted);line-height:1.35;overflow:hidden;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical}.tools .connect-tile[data-state=\"connected\"]>span:not(.brand-mark){color:var(--so-success)}.tools .connect-local{grid-column:1/-1}.tools .connect-local>span:not(.brand-mark){-webkit-line-clamp:unset}.tools .connect-problem{margin:0}.tools .connect-problem:focus{outline:2px solid var(--so-accent);outline-offset:2px}.tools .connect-tile:disabled{cursor:default;opacity:.6}@media(max-width:600px){.tools .connect-grid{grid-template-columns:1fr 1fr}.tools .connect-tile:not(.connect-local)>span:not(.brand-mark){display:none}.tools .connect-local>span:not(.brand-mark){grid-column:2}.tools .connect-tile{min-height:52px;padding:8px 10px}.tools .connect-tile .brand-mark{grid-row:auto}.tools input,.tools select{font-size:16px}.tools .card{padding:14px}}";
|
|
3
3
|
export type ToolsView = {
|
|
4
4
|
repo: string;
|
|
5
5
|
project: string;
|
|
@@ -10,6 +10,7 @@ export type ToolsView = {
|
|
|
10
10
|
about: string;
|
|
11
11
|
state: "connected" | "open" | "taken";
|
|
12
12
|
local?: true;
|
|
13
|
+
research?: string;
|
|
13
14
|
}[];
|
|
14
15
|
kit: string | null;
|
|
15
16
|
/** The service a link asked for (a kit's checklist, the lead): its own button under the password. */
|