@llblab/pi-kit 0.1.13 → 0.3.0
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/AGENTS.md +1 -0
- package/CHANGELOG.md +10 -0
- package/README.md +2 -2
- package/node_modules/@llblab/pi-actors/AGENTS.md +5 -3
- package/node_modules/@llblab/pi-actors/BACKLOG.md +1 -1
- package/node_modules/@llblab/pi-actors/CHANGELOG.md +15 -0
- package/node_modules/@llblab/pi-actors/README.md +5 -3
- package/node_modules/@llblab/pi-actors/dist/index.js +4 -1
- package/node_modules/@llblab/pi-actors/dist/lib/async-runs.d.ts +2 -2
- package/node_modules/@llblab/pi-actors/dist/lib/async-runs.js +42 -19
- package/node_modules/@llblab/pi-actors/dist/lib/extension-runtime.d.ts +2 -1
- package/node_modules/@llblab/pi-actors/dist/lib/extension-runtime.js +7 -2
- package/node_modules/@llblab/pi-actors/dist/lib/limits.d.ts +9 -0
- package/node_modules/@llblab/pi-actors/dist/lib/limits.js +9 -0
- package/node_modules/@llblab/pi-actors/dist/lib/observability.d.ts +10 -11
- package/node_modules/@llblab/pi-actors/dist/lib/observability.js +81 -56
- package/node_modules/@llblab/pi-actors/dist/lib/pi.d.ts +31 -0
- package/node_modules/@llblab/pi-actors/dist/lib/pi.js +180 -0
- package/node_modules/@llblab/pi-actors/dist/lib/run-delivery.d.ts +115 -0
- package/node_modules/@llblab/pi-actors/dist/lib/run-delivery.js +623 -0
- package/node_modules/@llblab/pi-actors/dist/lib/run-ui-runtime.d.ts +3 -0
- package/node_modules/@llblab/pi-actors/dist/lib/run-ui-runtime.js +341 -13
- package/node_modules/@llblab/pi-actors/dist/lib/runs-trace.d.ts +1 -1
- package/node_modules/@llblab/pi-actors/dist/lib/runs-trace.js +5 -3
- package/node_modules/@llblab/pi-actors/dist/lib/session-evidence.d.ts +16 -0
- package/node_modules/@llblab/pi-actors/dist/lib/session-evidence.js +143 -0
- package/node_modules/@llblab/pi-actors/dist/lib/temp.js +1 -1
- package/node_modules/@llblab/pi-actors/dist/lib/tools-inspect.js +3 -1
- package/node_modules/@llblab/pi-actors/dist/scripts/async-runner.mjs +5 -19
- package/node_modules/@llblab/pi-actors/dist/skills/actors/SKILL.md +2 -2
- package/node_modules/@llblab/pi-actors/dist/skills/actors/references/runs.md +1 -1
- package/node_modules/@llblab/pi-actors/dist/skills/swarm/SKILL.md +1 -1
- package/node_modules/@llblab/pi-actors/docs/README.md +1 -0
- package/node_modules/@llblab/pi-actors/docs/async-runs.md +8 -4
- package/node_modules/@llblab/pi-actors/docs/coordinator-delivery.md +207 -0
- package/node_modules/@llblab/pi-actors/index.ts +4 -1
- package/node_modules/@llblab/pi-actors/lib/async-runs.ts +42 -21
- package/node_modules/@llblab/pi-actors/lib/extension-runtime.ts +8 -3
- package/node_modules/@llblab/pi-actors/lib/limits.ts +9 -0
- package/node_modules/@llblab/pi-actors/lib/observability.ts +97 -78
- package/node_modules/@llblab/pi-actors/lib/pi.ts +210 -0
- package/node_modules/@llblab/pi-actors/lib/run-delivery.ts +800 -0
- package/node_modules/@llblab/pi-actors/lib/run-ui-runtime.ts +370 -18
- package/node_modules/@llblab/pi-actors/lib/runs-trace.ts +6 -4
- package/node_modules/@llblab/pi-actors/lib/session-evidence.ts +153 -0
- package/node_modules/@llblab/pi-actors/lib/temp.ts +1 -1
- package/node_modules/@llblab/pi-actors/lib/tools-inspect.ts +4 -1
- package/node_modules/@llblab/pi-actors/package.json +3 -3
- package/node_modules/@llblab/pi-actors/scripts/async-runner.mjs +5 -19
- package/node_modules/@llblab/pi-actors/skills/actors/SKILL.md +2 -2
- package/node_modules/@llblab/pi-actors/skills/actors/references/runs.md +1 -1
- package/node_modules/@llblab/pi-actors/skills/swarm/SKILL.md +1 -1
- package/node_modules/@llblab/pi-telegram/AGENTS.md +4 -4
- package/node_modules/@llblab/pi-telegram/CHANGELOG.md +25 -0
- package/node_modules/@llblab/pi-telegram/README.md +4 -4
- package/node_modules/@llblab/pi-telegram/docs/activity.md +4 -4
- package/node_modules/@llblab/pi-telegram/docs/architecture.md +10 -10
- package/node_modules/@llblab/pi-telegram/docs/compact-matrix-literal.md +16 -14
- package/node_modules/@llblab/pi-telegram/docs/inbound.md +1 -1
- package/node_modules/@llblab/pi-telegram/docs/outbound.md +13 -22
- package/node_modules/@llblab/pi-telegram/docs/public-api.md +6 -7
- package/node_modules/@llblab/pi-telegram/docs/ui-style.md +4 -5
- package/node_modules/@llblab/pi-telegram/docs/voice.md +12 -2
- package/node_modules/@llblab/pi-telegram/index.ts +0 -1
- package/node_modules/@llblab/pi-telegram/lib/activity.ts +10 -5
- package/node_modules/@llblab/pi-telegram/lib/bindings.ts +16 -17
- package/node_modules/@llblab/pi-telegram/lib/bus-leader.ts +1 -1
- package/node_modules/@llblab/pi-telegram/lib/commands.ts +16 -6
- package/node_modules/@llblab/pi-telegram/lib/config.ts +25 -25
- package/node_modules/@llblab/pi-telegram/lib/media.ts +12 -2
- package/node_modules/@llblab/pi-telegram/lib/menu-settings.ts +10 -73
- package/node_modules/@llblab/pi-telegram/lib/outbound-buttons.ts +9 -8
- package/node_modules/@llblab/pi-telegram/lib/outbound-markup.ts +212 -82
- package/node_modules/@llblab/pi-telegram/lib/routing.ts +78 -36
- package/node_modules/@llblab/pi-telegram/lib/status.ts +23 -4
- package/node_modules/@llblab/pi-telegram/lib/turns.ts +10 -1
- package/node_modules/@llblab/pi-telegram/lib/updates.ts +1 -1
- package/node_modules/@llblab/pi-telegram/package.json +1 -1
- package/node_modules/@llblab/pi-telegram/skills/generated-control-surface/SKILL.md +61 -205
- package/node_modules/@llblab/pi-telegram/skills/generated-control-surface/references/capability-adapters.md +27 -0
- package/node_modules/@llblab/pi-telegram/skills/generated-control-surface/references/layout-and-state.md +35 -0
- package/node_modules/@llblab/pi-telegram/skills/telegram-bridge/SKILL.md +70 -110
- package/node_modules/@llblab/pi-telegram/skills/telegram-bridge/references/configuration.md +15 -0
- package/node_modules/@llblab/pi-telegram/skills/telegram-bridge/references/delivery-and-threads.md +27 -0
- package/node_modules/@llblab/pi-telegram/skills/telegram-bridge/references/diagnosis.md +14 -0
- package/package.json +3 -3
|
@@ -107,8 +107,9 @@ function appendTelegramSourceAttachmentSection(
|
|
|
107
107
|
text: string,
|
|
108
108
|
from: string | undefined,
|
|
109
109
|
files: Pick<Media.DownloadedTelegramFile, "path">[],
|
|
110
|
+
outputs: readonly string[] = [],
|
|
110
111
|
): string {
|
|
111
|
-
if (files.length === 0) return text;
|
|
112
|
+
if (files.length === 0 && outputs.length === 0) return text;
|
|
112
113
|
const dirs = [...new Set(files.map((file) => dirname(file.path)))];
|
|
113
114
|
const sameDir = dirs.length === 1;
|
|
114
115
|
const source = from ? `|from:${from}` : "";
|
|
@@ -118,8 +119,15 @@ function appendTelegramSourceAttachmentSection(
|
|
|
118
119
|
const items = sameDir
|
|
119
120
|
? files.map((file) => `/${basename(file.path)}`)
|
|
120
121
|
: files.map((file) => file.path);
|
|
121
|
-
const
|
|
122
|
-
|
|
122
|
+
const sections = text ? [text] : [];
|
|
123
|
+
if (items.length > 0) {
|
|
124
|
+
sections.push(`${header}\n${items.map((item) => `- ${item}`).join("\n")}`);
|
|
125
|
+
}
|
|
126
|
+
if (outputs.length > 0) {
|
|
127
|
+
const outputHeader = `[outputs${source}]`;
|
|
128
|
+
sections.push(`${outputHeader}\n${outputs.map((output) => `- ${output}`).join("\n")}`);
|
|
129
|
+
}
|
|
130
|
+
return sections.join("\n\n");
|
|
123
131
|
}
|
|
124
132
|
|
|
125
133
|
function getContextCwd(ctx: unknown): string | undefined {
|
|
@@ -269,7 +277,7 @@ function getTelegramRoutableThreadRecords(
|
|
|
269
277
|
|
|
270
278
|
function formatTelegramAllTabMenuChooserText(command: string): string {
|
|
271
279
|
return [
|
|
272
|
-
"<b>🧵 Choose target thread
|
|
280
|
+
"<b>🧵 Choose target thread:</b>",
|
|
273
281
|
"",
|
|
274
282
|
`You used <code>/${escapeHtml(command)}</code> from the <b>All</b> tab.`,
|
|
275
283
|
"Select the Pi thread that should handle it:",
|
|
@@ -332,7 +340,7 @@ function buildTelegramUnboundRerouteRestoreChooserMarkup(
|
|
|
332
340
|
|
|
333
341
|
function formatTelegramUnboundRerouteRestoreChooserText(): string {
|
|
334
342
|
return [
|
|
335
|
-
"<b>🧵 Replace/restore Telegram thread
|
|
343
|
+
"<b>🧵 Replace/restore Telegram thread:</b>",
|
|
336
344
|
"",
|
|
337
345
|
"Choose the Pi instance to move to this new Telegram thread:",
|
|
338
346
|
].join("\n");
|
|
@@ -340,7 +348,7 @@ function formatTelegramUnboundRerouteRestoreChooserText(): string {
|
|
|
340
348
|
|
|
341
349
|
function formatTelegramUnboundTopicGuidance(): string {
|
|
342
350
|
return [
|
|
343
|
-
"
|
|
351
|
+
"<b>⚠️ New thread is not a Pi instance.</b>",
|
|
344
352
|
"",
|
|
345
353
|
"To create a bound Telegram tab:",
|
|
346
354
|
"<code>1.</code> Start another Pi instance in your terminal.",
|
|
@@ -358,7 +366,7 @@ function formatTelegramUnboundRerouteChooserText(
|
|
|
358
366
|
options: { includeGuidance?: boolean } = {},
|
|
359
367
|
): string {
|
|
360
368
|
const rerouteText = [
|
|
361
|
-
"
|
|
369
|
+
"<b>🧵 Choose target thread:</b>",
|
|
362
370
|
"",
|
|
363
371
|
"Your message is still in this Telegram thread.",
|
|
364
372
|
"Select the Pi thread that should handle it:",
|
|
@@ -751,6 +759,42 @@ export function createTelegramInboundRouteRuntime<
|
|
|
751
759
|
);
|
|
752
760
|
}
|
|
753
761
|
};
|
|
762
|
+
const resolveTelegramThreadLabel = (message: {
|
|
763
|
+
chat: { id: number };
|
|
764
|
+
message_thread_id?: number;
|
|
765
|
+
}): string | undefined => {
|
|
766
|
+
const chatId = message.chat.id;
|
|
767
|
+
const threadId = message.message_thread_id;
|
|
768
|
+
if (!threadId) return undefined;
|
|
769
|
+
const localLabel = deps.getLocalThreadLabelForTarget?.({ chatId, threadId });
|
|
770
|
+
if (localLabel) return localLabel;
|
|
771
|
+
if (!deps.threadStore) return undefined;
|
|
772
|
+
const records = deps.threadStore.list();
|
|
773
|
+
const currentInstanceId = deps.getCurrentInstanceId?.();
|
|
774
|
+
for (const record of records) {
|
|
775
|
+
if (
|
|
776
|
+
record.target.chatId !== chatId ||
|
|
777
|
+
record.target.threadId !== threadId
|
|
778
|
+
) {
|
|
779
|
+
continue;
|
|
780
|
+
}
|
|
781
|
+
if (
|
|
782
|
+
currentInstanceId &&
|
|
783
|
+
record.instanceId &&
|
|
784
|
+
record.instanceId !== currentInstanceId
|
|
785
|
+
) {
|
|
786
|
+
continue;
|
|
787
|
+
}
|
|
788
|
+
return record.threadName &&
|
|
789
|
+
Threads.isTelegramTopicThreadNameValidForSlot(
|
|
790
|
+
record.threadName,
|
|
791
|
+
record.slot,
|
|
792
|
+
)
|
|
793
|
+
? record.threadName
|
|
794
|
+
: getRestoredThreadName(record, record.slot ?? "");
|
|
795
|
+
}
|
|
796
|
+
return undefined;
|
|
797
|
+
};
|
|
754
798
|
const createAdmissionReceipts = (
|
|
755
799
|
queueKind: Queue.TelegramQueueItemKind,
|
|
756
800
|
sources: readonly unknown[],
|
|
@@ -1620,6 +1664,13 @@ export function createTelegramInboundRouteRuntime<
|
|
|
1620
1664
|
replyToMessageId: messageId,
|
|
1621
1665
|
queueOrder,
|
|
1622
1666
|
action,
|
|
1667
|
+
telegramPrefix: Turns.createTelegramTurnPrefix({
|
|
1668
|
+
thread: resolveTelegramThreadLabel({
|
|
1669
|
+
chat: { id: chatId },
|
|
1670
|
+
message_thread_id:
|
|
1671
|
+
buttonQuery.message?.message_thread_id,
|
|
1672
|
+
}),
|
|
1673
|
+
}),
|
|
1623
1674
|
}),
|
|
1624
1675
|
...(admissionReceipts.length > 0 ? { admissionReceipts } : {}),
|
|
1625
1676
|
};
|
|
@@ -1762,34 +1813,7 @@ export function createTelegramInboundRouteRuntime<
|
|
|
1762
1813
|
|
|
1763
1814
|
// Voice policy resolves missing, invalid, and legacy manual config to hidden.
|
|
1764
1815
|
getVoiceReplyMode: () => getTelegramVoiceReplyMode(deps.configStore.get()),
|
|
1765
|
-
getTelegramThreadLabel
|
|
1766
|
-
if (!deps.threadStore) return undefined;
|
|
1767
|
-
const chatId = message.chat.id;
|
|
1768
|
-
const threadId = message.message_thread_id;
|
|
1769
|
-
if (!threadId) return undefined;
|
|
1770
|
-
const localLabel = deps.getLocalThreadLabelForTarget?.({
|
|
1771
|
-
chatId,
|
|
1772
|
-
threadId,
|
|
1773
|
-
});
|
|
1774
|
-
if (localLabel) return localLabel;
|
|
1775
|
-
const records = deps.threadStore.list();
|
|
1776
|
-
const currentInstanceId = deps.getCurrentInstanceId?.();
|
|
1777
|
-
for (const r of records) {
|
|
1778
|
-
if (r.target.chatId !== chatId || r.target.threadId !== threadId)
|
|
1779
|
-
continue;
|
|
1780
|
-
if (
|
|
1781
|
-
currentInstanceId &&
|
|
1782
|
-
r.instanceId &&
|
|
1783
|
-
r.instanceId !== currentInstanceId
|
|
1784
|
-
)
|
|
1785
|
-
continue;
|
|
1786
|
-
return r.threadName &&
|
|
1787
|
-
Threads.isTelegramTopicThreadNameValidForSlot(r.threadName, r.slot)
|
|
1788
|
-
? r.threadName
|
|
1789
|
-
: getRestoredThreadName(r, r.slot ?? "");
|
|
1790
|
-
}
|
|
1791
|
-
return undefined;
|
|
1792
|
-
},
|
|
1816
|
+
getTelegramThreadLabel: resolveTelegramThreadLabel,
|
|
1793
1817
|
});
|
|
1794
1818
|
const enqueueContinueTurn = async (
|
|
1795
1819
|
message: TMessage,
|
|
@@ -1877,6 +1901,18 @@ export function createTelegramInboundRouteRuntime<
|
|
|
1877
1901
|
getPromptTemplateCommands,
|
|
1878
1902
|
persistConfig: deps.configStore.persist,
|
|
1879
1903
|
sendTextReply: deps.sendTextReply,
|
|
1904
|
+
getActiveTurnReply: () => {
|
|
1905
|
+
const activeTurn = deps.activeTurnRuntime.get();
|
|
1906
|
+
if (!activeTurn) return undefined;
|
|
1907
|
+
return async (text, options) => {
|
|
1908
|
+
await deps.sendTextReply(
|
|
1909
|
+
activeTurn.chatId,
|
|
1910
|
+
activeTurn.replyToMessageId,
|
|
1911
|
+
text,
|
|
1912
|
+
{ target: activeTurn.target, parseMode: options?.parseMode },
|
|
1913
|
+
);
|
|
1914
|
+
};
|
|
1915
|
+
},
|
|
1880
1916
|
sendInteractiveMessage: deps.sendInteractiveMessage,
|
|
1881
1917
|
recordRuntimeEvent: deps.recordRuntimeEvent,
|
|
1882
1918
|
});
|
|
@@ -2265,6 +2301,11 @@ export function createTelegramInboundRouteRuntime<
|
|
|
2265
2301
|
)
|
|
2266
2302
|
: [];
|
|
2267
2303
|
assertExecutionCurrent();
|
|
2304
|
+
const processedReply =
|
|
2305
|
+
replyFiles.length > 0
|
|
2306
|
+
? await deps.inboundHandlerRuntime.process(replyFiles, "", ctx)
|
|
2307
|
+
: undefined;
|
|
2308
|
+
assertExecutionCurrent();
|
|
2268
2309
|
const files = await Media.downloadTelegramMessageFiles([guestMsg], {
|
|
2269
2310
|
downloadFile: deps.downloadFile,
|
|
2270
2311
|
});
|
|
@@ -2285,7 +2326,8 @@ export function createTelegramInboundRouteRuntime<
|
|
|
2285
2326
|
sourceContext = appendTelegramSourceAttachmentSection(
|
|
2286
2327
|
replyBlock,
|
|
2287
2328
|
replyPeer,
|
|
2288
|
-
replyFiles,
|
|
2329
|
+
processedReply?.promptFiles ?? replyFiles,
|
|
2330
|
+
processedReply?.handlerOutputs,
|
|
2289
2331
|
);
|
|
2290
2332
|
}
|
|
2291
2333
|
const promptText = Turns.buildTelegramTurnPrompt({
|
|
@@ -14,6 +14,7 @@ export interface TelegramUsageStats {
|
|
|
14
14
|
totalCacheRead: number;
|
|
15
15
|
totalCacheWrite: number;
|
|
16
16
|
totalCost: number;
|
|
17
|
+
latestCacheHitRate?: number;
|
|
17
18
|
}
|
|
18
19
|
|
|
19
20
|
interface TelegramUsageMessage {
|
|
@@ -1473,6 +1474,9 @@ function collectUsageStats(ctx: TelegramStatusContext): TelegramUsageStats {
|
|
|
1473
1474
|
stats.totalCacheRead += usage.cacheRead;
|
|
1474
1475
|
stats.totalCacheWrite += usage.cacheWrite;
|
|
1475
1476
|
stats.totalCost += usage.cost.total;
|
|
1477
|
+
const promptTokens = usage.input + usage.cacheRead + usage.cacheWrite;
|
|
1478
|
+
stats.latestCacheHitRate =
|
|
1479
|
+
promptTokens > 0 ? (usage.cacheRead / promptTokens) * 100 : undefined;
|
|
1476
1480
|
}
|
|
1477
1481
|
return stats;
|
|
1478
1482
|
}
|
|
@@ -1490,11 +1494,22 @@ function buildUsageSummary(stats: TelegramUsageStats): string | undefined {
|
|
|
1490
1494
|
const tokenParts: string[] = [];
|
|
1491
1495
|
if (stats.totalInput) tokenParts.push(`↑${formatTokens(stats.totalInput)}`);
|
|
1492
1496
|
if (stats.totalOutput) tokenParts.push(`↓${formatTokens(stats.totalOutput)}`);
|
|
1497
|
+
return tokenParts.length > 0 ? tokenParts.join(" ") : undefined;
|
|
1498
|
+
}
|
|
1499
|
+
|
|
1500
|
+
function buildCacheSummary(stats: TelegramUsageStats): string | undefined {
|
|
1501
|
+
const cacheParts: string[] = [];
|
|
1493
1502
|
if (stats.totalCacheRead)
|
|
1494
|
-
|
|
1503
|
+
cacheParts.push(`R${formatTokens(stats.totalCacheRead)}`);
|
|
1495
1504
|
if (stats.totalCacheWrite)
|
|
1496
|
-
|
|
1497
|
-
|
|
1505
|
+
cacheParts.push(`W${formatTokens(stats.totalCacheWrite)}`);
|
|
1506
|
+
if (
|
|
1507
|
+
(stats.totalCacheRead > 0 || stats.totalCacheWrite > 0) &&
|
|
1508
|
+
stats.latestCacheHitRate !== undefined
|
|
1509
|
+
) {
|
|
1510
|
+
cacheParts.push(`CH${stats.latestCacheHitRate.toFixed(1)}%`);
|
|
1511
|
+
}
|
|
1512
|
+
return cacheParts.length > 0 ? cacheParts.join(" ") : undefined;
|
|
1498
1513
|
}
|
|
1499
1514
|
|
|
1500
1515
|
function buildCostSummary(
|
|
@@ -1547,9 +1562,13 @@ export function buildStatusHtml(
|
|
|
1547
1562
|
),
|
|
1548
1563
|
];
|
|
1549
1564
|
const usageSummary = buildUsageSummary(stats);
|
|
1565
|
+
const cacheSummary = buildCacheSummary(stats);
|
|
1550
1566
|
const costSummary = buildCostSummary(stats, usesSubscription);
|
|
1551
1567
|
if (usageSummary) {
|
|
1552
|
-
lines.push(buildStatusRow("
|
|
1568
|
+
lines.push(buildStatusRow("Tokens", usageSummary));
|
|
1569
|
+
}
|
|
1570
|
+
if (cacheSummary) {
|
|
1571
|
+
lines.push(buildStatusRow("Cache", cacheSummary));
|
|
1553
1572
|
}
|
|
1554
1573
|
if (costSummary) {
|
|
1555
1574
|
lines.push(buildStatusRow("Cost", costSummary));
|
|
@@ -468,8 +468,17 @@ export function createTelegramPromptTurnRuntimeBuilder<
|
|
|
468
468
|
)
|
|
469
469
|
: [];
|
|
470
470
|
if (firstMessage) deps.assertExecutionCurrent?.(firstMessage);
|
|
471
|
+
const processedReply =
|
|
472
|
+
deps.processAttachments && replyFiles.length > 0
|
|
473
|
+
? await deps.processAttachments(replyFiles, "", ctx as TContext)
|
|
474
|
+
: undefined;
|
|
475
|
+
if (firstMessage) deps.assertExecutionCurrent?.(firstMessage);
|
|
471
476
|
const replyContext = firstMessage
|
|
472
|
-
? buildTelegramReplyContextBlock(
|
|
477
|
+
? buildTelegramReplyContextBlock(
|
|
478
|
+
firstMessage,
|
|
479
|
+
processedReply?.promptFiles ?? replyFiles,
|
|
480
|
+
processedReply?.handlerOutputs,
|
|
481
|
+
)
|
|
473
482
|
: "";
|
|
474
483
|
const forwardEntries = messages.flatMap((message) => {
|
|
475
484
|
const context = extractTelegramForwardContextText(
|
|
@@ -895,7 +895,7 @@ const TELEGRAM_UNAUTHORIZED_DENIAL_COPY = "Access denied.";
|
|
|
895
895
|
|
|
896
896
|
function formatTelegramUnauthorizedDenial(format: "plain" | "html"): string {
|
|
897
897
|
return format === "html"
|
|
898
|
-
?
|
|
898
|
+
? `<b>🚫 ${TELEGRAM_UNAUTHORIZED_DENIAL_COPY}</b>`
|
|
899
899
|
: `🚫 ${TELEGRAM_UNAUTHORIZED_DENIAL_COPY}`;
|
|
900
900
|
}
|
|
901
901
|
|
|
@@ -1,249 +1,105 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: generated-control-surface
|
|
3
|
-
description: Proactively
|
|
3
|
+
description: Proactively generate truthful prompt-button controls; every active surface emits useful buttons with semantic emoji labels, while stable deterministic loops route to Generative Apps.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Generated Control Surface
|
|
7
7
|
|
|
8
|
-
Compile a temporary
|
|
9
|
-
|
|
10
|
-
## Primitive
|
|
8
|
+
Compile a temporary interface from current evidence, available capabilities, and user intent:
|
|
11
9
|
|
|
12
10
|
```text
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
current evidence + available acts + user intent
|
|
16
|
-
→ compact state projection → contextual controls
|
|
17
|
-
→ next prompt → authorized act → fresh projection
|
|
11
|
+
state + capabilities + intent → projection + likely next actions
|
|
18
12
|
```
|
|
19
13
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
The primitive belongs to the Surface plane: it projects State, exposes Agency capabilities, and preserves Constitution constraints without absorbing any of those owners. Its reusable competence lives in this Skill so quality depends less on rediscovering interface policy in each turn.
|
|
23
|
-
|
|
24
|
-
## Scope
|
|
25
|
-
|
|
26
|
-
Use this Skill only to synthesize a state-derived prompt-button surface. Operating or modifying an existing Telegram bridge menu, callback interface, fixed frontend, runtime-owned control, or installed Generative App stays with that subsystem and does not route here merely because it contains buttons.
|
|
27
|
-
|
|
28
|
-
This Skill and `generative-apps` share one logical button-matrix and `label + prompt` interaction model while retaining different execution owners. On Telegram, the bridge runtime owns the full JSON/CML action notation: this Skill emits an ephemeral surface from current context, while a Generative App returns reusable views through its script ABI. Shared rendering does not justify a third button Skill or move transport grammar into either interaction Skill.
|
|
29
|
-
|
|
30
|
-
When a generated surface reveals repeated stable interaction with bounded state and deterministic transitions, load the complementary `generative-apps` Skill and consider compiling that loop. A Generative App may retain ordinary model-mediated prompt buttons beside deterministic bound methods, so only the stable actions need bypass inference. Conversely, keep one-off, interpretive, changing, and context-heavy interaction here when a reusable script would add no concrete latency, token, cost, reliability, or UX value.
|
|
31
|
-
|
|
32
|
-
On Telegram-originated turns, evaluate this Skill proactively rather than waiting for the user to ask for buttons. A connected Telegram session, available button syntax, or proactive projection of local output is capability evidence, not activation intent: do not load this Skill for an unrelated local/TUI prompt merely because its answer may also appear in Telegram. Load and apply it when the current turn is Telegram-originated or the user explicitly requests a prompt-button surface and a likely next decision, approval, navigation step, inspection, or bounded action can be made materially easier through controls; its correct output may still contain zero buttons when the admission test fails.
|
|
33
|
-
|
|
34
|
-
A control surface may expose:
|
|
35
|
-
|
|
36
|
-
- Observation: status, evidence, progress, diagnostics, or summaries.
|
|
37
|
-
- Navigation: files, concepts, projects, artifacts, media, threads, or Actor Runs.
|
|
38
|
-
- Action: safe next operations over tools, workflows, services, or project state.
|
|
39
|
-
- Choice: alternatives, filters, priorities, approvals, or design decisions.
|
|
40
|
-
- Supervision: pause, continue, inspect, redirect, retry, or stop bounded work.
|
|
41
|
-
|
|
42
|
-
Console programs are one capability source, not the defining boundary. Use the real owner of each capability: a tool, API, repository, Actor runtime, filesystem, media system, documented workflow, or the explicit state of the conversation.
|
|
43
|
-
|
|
44
|
-
## Core Contract
|
|
45
|
-
|
|
46
|
-
- Generate controls from current evidence, an explicit contract, or clearly labeled conversational state.
|
|
47
|
-
- Keep domain state with its real owner; never invent a shadow navigation tree, task database, or application session.
|
|
48
|
-
- Make every button prompt minimally sufficient for a truthful continuation: reuse unambiguous visible conversational context, but include stable target, state, constraint, or freshness identity whenever omission could change the action.
|
|
49
|
-
- Treat a click as an ordinary user request subject to the same authority, validation, and safety rules as typed text.
|
|
50
|
-
- Never infer permission for destructive, privileged, credential-bearing, external, or irreversible work merely because a button exists.
|
|
51
|
-
- Do not encode secrets, hidden reasoning, credentials, private keys, tokens, cookies, wallet material, or sensitive content in labels or prompts.
|
|
52
|
-
- Show uncertainty, unavailable state, truncation, filtering, and stale evidence honestly.
|
|
53
|
-
- Prefer a few high-value controls over exhaustive action enumeration.
|
|
54
|
-
|
|
55
|
-
## Control Admission
|
|
56
|
-
|
|
57
|
-
Buttons are optional only when no candidate passes the admission test. Bias toward offering them whenever they materially shorten a likely feedback loop. If the user can approve, reject, refine, prioritize, redirect, inspect, or choose a concrete next step faster by tapping than by composing a reply, proactively expose the smallest useful control set without waiting to be asked for buttons.
|
|
58
|
-
|
|
59
|
-
On a Telegram-originated turn, emitting controls is required when the response asks the user for one or more bounded confirmations or choices, the likely answers can be represented truthfully in 2–6 safe controls, and no secret-bearing or high-impact ambiguity blocks their formulation. This includes blocking questions such as confirming scope, version, workflow classification, approval, or the next release step. Ask in prose when explanation is necessary, but attach the controls in the same reply; the availability of free-form typing is not a reason to omit them. A high-impact operation still uses the required confirmation flow rather than a one-tap execution shortcut.
|
|
60
|
-
|
|
61
|
-
Apply the same requirement at a workflow handoff even when the current user message itself was a complete correction or implementation command. Before concluding a Telegram reply, project the user's likely next intent from the active goal, recent trajectory, newly completed act, and available capabilities—not only from an explicitly pending question. Typical phase transitions include “prepare → release”, “inspect → approve”, “fix → rerun”, and “draft → send”. If one next action or a small alternative set is high-confidence, newly unblocked, truthfully expressible, and safe to request, emit 2–6 controls now instead of waiting for the user to restate the obvious next step. A narrowly completed subtask does not erase the parent intent or make the predictive handoff decorative.
|
|
62
|
-
|
|
63
|
-
This is anticipatory interaction, not generic suggestion generation. Prefer controls that advance the user's demonstrated workflow over broad capability menus, speculative side quests, or “What next?” buttons. A predicted high-impact action is offered as an explicit self-contained request or confirmation, never silently executed. When confidence is low or materially different next intents compete, omit controls or expose only the smallest clarifying choice.
|
|
64
|
-
|
|
65
|
-
Zero buttons remains preferable when controls would only decorate the answer, restate visible prose, solicit generic “What next?” input, expose an unclear consequence, save negligible effort, or when the user already issued a complete command and neither that command nor the inferred active workflow leaves a high-confidence immediate decision. A button earns its place by reducing response effort, ambiguity, turnaround time, or supervision cost while preserving an ordinary typed reply as a first-class option.
|
|
66
|
-
|
|
67
|
-
For status requests, show a compact `Refresh` control and bounded inspect/drill-down controls only when work is active, blocked, stale-sensitive, or otherwise actionable. A completed static status needs no buttons. Do not add destructive shortcuts or actions whose target and consequence are not yet clear.
|
|
68
|
-
|
|
69
|
-
## Feedback Leverage
|
|
70
|
-
|
|
71
|
-
Treat feedback compression as the primary reason to make controls more visible and proactive:
|
|
14
|
+
The surface projects reality; it does not own domain state, grant authority, or create a shadow application.
|
|
72
15
|
|
|
73
|
-
|
|
74
|
-
- Prefer controls for approval gates, bounded alternatives, priority changes, review verdicts, correction direction, and active-work supervision.
|
|
75
|
-
- Put the most likely or highest-leverage response first, while keeping labels neutral enough to avoid steering the decision dishonestly.
|
|
76
|
-
- Include an explicit free-form path in visible text when the listed choices cannot represent the full answer.
|
|
77
|
-
- Regenerate controls after feedback so the next surface reflects the new decision rather than repeating stale options.
|
|
78
|
-
- Omit controls when the user is already expressing a clear command and no immediate follow-up decision is needed.
|
|
16
|
+
## Admission
|
|
79
17
|
|
|
80
|
-
|
|
18
|
+
Proactively use controls whenever a tap can reduce response effort, ambiguity, turnaround time, or supervision cost. On a prompt-button transport, every response produced under this Skill must include at least one useful button; never finish with prose alone. A bounded confirmation or choice should expose 2–6 safe concrete actions.
|
|
81
19
|
|
|
82
|
-
|
|
20
|
+
At workflow handoff, offer a small high-confidence next-action set when the completed step clearly unlocks it. Preserve free-form reply when choices are not exhaustive. When no domain mutation qualifies, offer the most useful truthful continuation—such as inspect details, refine scope, refresh mutable evidence, navigate back, or continue the parent workflow—rather than a decorative control or generic “What next?”.
|
|
83
21
|
|
|
84
|
-
|
|
85
|
-
2. A compact projection of relevant state, evidence, choices, or output.
|
|
86
|
-
3. Provenance when it matters: target, source, timestamp, run identity, status, or truncation note.
|
|
87
|
-
4. Buttons for likely next intents.
|
|
88
|
-
5. `Back` or `Up` for hierarchy navigation when meaningful.
|
|
89
|
-
6. `Refresh` when the projected state can change.
|
|
22
|
+
Every button must advance, inspect, clarify, recover, navigate, or supervise the current intent. Never duplicate visible prose, represent unclear consequences, or repeat a command that introduces no new decision.
|
|
90
23
|
|
|
91
|
-
|
|
24
|
+
## Ownership And Truth
|
|
92
25
|
|
|
93
|
-
|
|
26
|
+
Identify one controlled object, target, and capability owner. Build from one declared truth mode when ambiguity matters:
|
|
94
27
|
|
|
95
|
-
|
|
28
|
+
- **Live:** Freshly inspected mutable state.
|
|
29
|
+
- **Contract:** Stable documented capability.
|
|
30
|
+
- **Conversation:** Choices established in the dialogue.
|
|
31
|
+
- **Adapted:** A labeled subset or transformation.
|
|
96
32
|
|
|
97
|
-
|
|
33
|
+
Never present remembered or inferred state as live. Preserve material identity, ordering, values, warnings, failures, authority, and completeness. Label filtering, truncation, pagination, and unavailable evidence. Refresh affected state after mutation before claiming success or rendering dependent controls.
|
|
98
34
|
|
|
99
|
-
|
|
35
|
+
Use the real capability owner—tool, API, repository, Actor runtime, filesystem, media system, workflow, or conversation. Do not invent parallel state, lifecycle, navigation, or callbacks.
|
|
100
36
|
|
|
101
|
-
|
|
102
|
-
- Contract: stable documented capabilities or choices.
|
|
103
|
-
- Conversation: alternatives or intents established in the current dialogue.
|
|
104
|
-
- Adapted: bounded or transformed output whose omissions are stated.
|
|
37
|
+
## Surface Contract
|
|
105
38
|
|
|
106
|
-
|
|
39
|
+
A surface is an ordered ragged sequence of rows. Each button carries:
|
|
107
40
|
|
|
108
|
-
|
|
41
|
+
- A short, distinct label.
|
|
42
|
+
- The smallest self-contained next-request prompt.
|
|
43
|
+
- Optional presentation state supported by the transport.
|
|
109
44
|
|
|
110
|
-
|
|
45
|
+
Prompts must name any target, operation, constraint, or freshness identity whose omission could change the action. Reuse visible context only when it remains unambiguous under delayed or reordered clicks. Never encode volatile output that should be freshly inspected.
|
|
111
46
|
|
|
112
|
-
-
|
|
113
|
-
- Hide material warnings or unavailable evidence.
|
|
114
|
-
- Present a subset as complete.
|
|
115
|
-
- Change identifiers, values, causal order, or authority.
|
|
116
|
-
- Turn a proposal into completed state.
|
|
47
|
+
Every generated human-readable action label must use `emoji + space + text`; emoji-free text labels are invalid. Choose the emoji by action semantics, keep its meaning consistent, and never rely on emoji or color alone. Coordinates, established symbolic controls, and intentionally spatial glyphs already satisfy the marker role through their domain grammar. If prompt buttons are unavailable, preserve the same choices as a numbered list.
|
|
117
48
|
|
|
118
|
-
|
|
49
|
+
## Layout Kernel
|
|
119
50
|
|
|
120
|
-
|
|
51
|
+
- Use one full-width row for an independent, primary, long, or consequential action.
|
|
52
|
+
- Use two columns only for unmistakably short textual peers.
|
|
53
|
+
- Reserve three through eight columns for compact position-bearing glyphs or codes.
|
|
54
|
+
- Preserve hierarchy and reading order; never pad, duplicate, or shorten necessary wording for symmetry.
|
|
55
|
+
- Use Back/Up only for real hierarchy and Refresh only for mutable projections.
|
|
56
|
+
- Prefer 2–6 decision controls. Paginate or group larger non-spatial collections.
|
|
121
57
|
|
|
122
|
-
|
|
58
|
+
For complex grids, navigation collections, or stateful repeated clicks, read [`references/layout-and-state.md`](./references/layout-and-state.md).
|
|
123
59
|
|
|
124
|
-
|
|
60
|
+
Serialize the resulting rows with the active transport contract. This Skill owns admission and composition, not transport syntax.
|
|
125
61
|
|
|
126
|
-
|
|
127
|
-
2. A distinct confirmation button requests the exact operation.
|
|
62
|
+
## Safety
|
|
128
63
|
|
|
129
|
-
|
|
64
|
+
A click is an ordinary user request under the same authority and validation rules as typed text. Never infer permission from the existence of a button.
|
|
130
65
|
|
|
131
|
-
|
|
66
|
+
Classify actions as read-only, ordinary mutation, privileged, destructive, secret-bearing, external, or irreversible. High-impact actions use two stages:
|
|
132
67
|
|
|
133
|
-
|
|
68
|
+
1. Open a confirmation surface naming exact target, effect, and recovery boundary.
|
|
69
|
+
2. Offer a distinct request for the exact operation.
|
|
134
70
|
|
|
135
|
-
|
|
71
|
+
Re-check mutable targets immediately before execution. Never expose secrets, credentials, hidden reasoning, private keys, tokens, cookies, wallet material, or sensitive content in labels, prompts, or projections. Access denial never authorizes privilege escalation.
|
|
136
72
|
|
|
137
|
-
|
|
73
|
+
## Reuse Boundary
|
|
138
74
|
|
|
139
|
-
|
|
140
|
-
- Use a singleton full-width row for a structurally independent, pinned, primary, summary, or high-consequence action, and whenever label length makes horizontal grouping cramped or ambiguous.
|
|
141
|
-
- Vary row widths intentionally—for example `1 → 2 → 4 → 1 → 2`—and never pad a row with empty, duplicate, or no-op controls merely to produce uniform dimensions.
|
|
142
|
-
- Preserve reading order across rows: orientation and structural navigation first, primary content or choices next, secondary controls afterward, and destructive actions visibly separated when present.
|
|
143
|
-
- Treat two columns as an earned compact mode, not the default: a pair normally fits when each label is no more than one emoji plus roughly two average-length words. If either label has more words, unusually long words, qualifiers, or likely wrapping, place each button on its own row. Use at most two columns for readable text labels; move additional peer choices into more semantic rows rather than compressing textual buttons across a phone-width line. Three through five columns are for short symbols, glyphs, coordinates, or compact codes whose position carries meaning. Six through eight may be used only for single-glyph or similarly minimal position-bearing labels whose grouping materially improves the interaction; a row of emoji-only controls may therefore legitimately use up to eight columns. Eight is the phone-width UX maximum: never generate a row of nine or more controls even though the parser has no artificial width cap. Never shorten necessary wording merely to increase row density; regroup or use full-width rows when labels need explanation, wrap ambiguously, or lose meaning without prose.
|
|
75
|
+
Keep one-off, interpretive, changing, and context-heavy interaction here. When state and transitions become stable, repeated, bounded, and deterministic, follow `generative-apps` and compile only the deterministic loop. Existing transport menus, runtime callbacks, and installed apps remain with their owners.
|
|
144
76
|
|
|
145
|
-
|
|
77
|
+
For capability-specific composition guidance, read only the applicable reference:
|
|
146
78
|
|
|
147
|
-
|
|
79
|
+
- Console, filesystem, workflows, Actor Runs, and design choices: [`references/capability-adapters.md`](./references/capability-adapters.md)
|
|
148
80
|
|
|
149
|
-
|
|
81
|
+
## Procedure
|
|
150
82
|
|
|
151
|
-
|
|
83
|
+
1. Identify intent, controlled object, owner, and truth mode.
|
|
84
|
+
2. Inspect only the evidence needed for a truthful projection.
|
|
85
|
+
3. Admit only high-leverage actions and classify their impact.
|
|
86
|
+
4. Arrange semantic rows, then serialize through the transport owner.
|
|
87
|
+
5. Treat the click as a new request, validate authority, act, and refresh reality.
|
|
152
88
|
|
|
153
|
-
|
|
154
|
-
- `2`: One binary or tightly coupled peer decision; neither control is visually subordinated.
|
|
155
|
-
- `1 → 2`: One orienting or primary action followed by a local peer pair.
|
|
156
|
-
- `2 → 1`: One peer mode/filter pair followed by an independent continuation or detail action.
|
|
157
|
-
- `1 → 2 → N×1`: Pinned structural navigation, compact traversal, then a vertical collection of independently readable items.
|
|
158
|
-
- `1 → 2 → 3 → 1`: Ragged staged control where context, local alternatives, denser short peers, and a separated terminal action have different semantic weight.
|
|
159
|
-
- Repeated `2`: Text-bearing choices distributed down the screen instead of compressed across it.
|
|
160
|
-
- `R×C`: A rectangular layout only when rows and columns map to genuine coordinates, repeated dimensions, or another stable spatial topology; keep `C ≤ 8`, while `R` may be substantially larger when preserving vertical continuity is useful.
|
|
161
|
-
|
|
162
|
-
Adapt a surface by identifying relationships, grouping only genuine peers, ordering groups by task hierarchy, applying label-pressure limits, and then choosing the least regular layout that remains immediately comprehensible. Do not select a catalog shape first and force the task into it.
|
|
163
|
-
|
|
164
|
-
Preserve the ordinary admission test: proactively offer an interactive surface even when the user did not request buttons when it materially reduces effort or demonstrates an available capability, but do not manufacture decorative interaction.
|
|
165
|
-
|
|
166
|
-
### Interaction State And Prompt Compression
|
|
167
|
-
|
|
168
|
-
- Encode the smallest sufficient action delta in repeated controls. When the visible surface and immediately preceding conversation establish one unambiguous state, a coordinate, symbol, identifier, or short verb can be the entire prompt; do not duplicate the same board, form, or selection state into every button payload.
|
|
169
|
-
- Keep compact prompts semantically closed over their context. If delivery may be delayed, reordered, routed elsewhere, or separated from the state projection, add a stable target or state identity rather than copying a large volatile snapshot.
|
|
170
|
-
- Keep trivial interaction state in the visible conversation. When state becomes too large, long-lived, or error-prone for reliable conversational reconstruction, persist a small human-auditable Markdown state artifact at a deterministic task-owned path and render from it. The artifact belongs to the underlying task or domain, not to this Skill as shadow application state.
|
|
171
|
-
- When transition rules are non-trivial or correctness-sensitive, use a small deterministic state-transition owner—script, module, tool, or existing domain API—that validates `current state + admitted action → next state`; let the model compile the surface from its result instead of informally simulating every transition. Do not create code or files for a trivial one-step interaction.
|
|
172
|
-
- Treat repeated clicks against current state, not stale button appearance. If an action is already consumed or unavailable, keep state unchanged and say so briefly. Preserve an occupied or selected button when spatial layout matters, using its label or selected style as the visual state; omit unavailable controls when layout does not matter. Transport-level disabled buttons are optional, not assumed.
|
|
173
|
-
- Preserve tap-ahead on transports where existing controls remain actionable and rapid clicks queue separate turns. In a source-then-destination interaction, persist the source selection but do not regenerate the board, enumerate destinations, or duplicate controls between the two prompts; emit at most a minimal acknowledgement and let the already visible surface carry the destination click. Regenerate after the completed transition, invalid input, or evidence that the transport cannot preserve the intermediate surface.
|
|
174
|
-
- Resolve coordinate selection by current state rather than rigid click parity. Clicking any currently selectable source selects or replaces the source and then waits; acknowledge a replacement tersely without regenerating the surface. Only a click that is not a selectable source becomes a destination attempt when a source is already selected, at which point the domain owner validates the transition. Without a selected source, a non-source coordinate is a no-op.
|
|
175
|
-
|
|
176
|
-
```html
|
|
177
|
-
<!-- telegram_button {"label":"🔍 Inspect run","prompt":"Inspect Run run:example read-only, summarize its current status and latest material evidence, then regenerate relevant supervision controls."} -->
|
|
178
|
-
<!-- telegram_button [{⬆️ Up|/}[{⬅️ Previous}{➡️ Next}]{📁 etc|/etc}] -->
|
|
179
|
-
```
|
|
180
|
-
|
|
181
|
-
Button prompts must:
|
|
182
|
-
|
|
183
|
-
- Preserve the user's language.
|
|
184
|
-
- Name exact targets when visible context does not make them unambiguous.
|
|
185
|
-
- Express one coherent next intent with the shortest sufficient action delta.
|
|
186
|
-
- Carry material safety and scope restrictions.
|
|
187
|
-
- Request fresh inspection when state may have changed.
|
|
188
|
-
- Avoid embedding volatile output that should be rediscovered.
|
|
189
|
-
|
|
190
|
-
Labels stay short, distinct, and scannable. Prefer an explicit `label` over exposing a long prompt as button text. Emoji are explicitly allowed and encouraged when one consistent semantic marker improves scanning or expressiveness; keep their meaning consistent across sibling controls, avoid decorative noise, and do not rely on emoji or color alone. If buttons are unavailable, render the same control surface as a numbered choice list.
|
|
191
|
-
|
|
192
|
-
## Capability Adapters
|
|
193
|
-
|
|
194
|
-
### Console And System
|
|
195
|
-
|
|
196
|
-
Use normal console programs as the capability owner. Check exit status and stderr before rendering success. Preserve complete output when reasonably sized; otherwise label pagination, filtering, head/tail, or ranked subsets. High-impact process, service, package, permission, shutdown, disk, and deletion actions require confirmation.
|
|
197
|
-
|
|
198
|
-
### Filesystem
|
|
199
|
-
|
|
200
|
-
Treat a user prompt that is exactly a plausible filesystem path—including `/`—as legitimate intent to render that location through a generated filesystem surface. Resolve and freshly inspect it before display. Directory surfaces use one stable navigation layout:
|
|
201
|
-
|
|
202
|
-
1. Pin `⬆️ Up` as the first full-width row whenever the current path is not filesystem root; its entire prompt is the exact parent path. Omit Up at `/`.
|
|
203
|
-
2. When page traversal exists, place `⬅️ Previous` and `➡️ Next` together in one compact row immediately after Up, omitting either unavailable direction. Page traversal re-inspects the directory and preserves a fixed 10-entry page size; moving Up opens the parent at page one.
|
|
204
|
-
3. Sort entries by semantic category before pagination: visible directories, hidden directories, visible files, then hidden files; sort names alphabetically within each category. Render at most 10 resulting entry buttons as full-width rows after structural navigation. Each label uses the entry name plus a semantic folder/file emoji, and its entire prompt may be the exact target path because this Skill defines path-only prompts as navigation intent.
|
|
205
|
-
4. Keep visible text to two compact status-style rows such as ``**Path:** `/home/llb` `` and ``**Entries:** `1–10 of 52` ``; do not join metadata with a middle dot and do not duplicate entry names as a plain or monospaced directory listing. Omit Refresh by default because resubmitting the current path already requests fresh rendering.
|
|
206
|
-
|
|
207
|
-
For pi-telegram, emit the complete filesystem control set—Up, compact page traversal, then current-page entries—in one `telegram_button` JSON matrix rather than repeating one hidden comment per button. If prompt buttons are unavailable or fail to render, preserve the same ordering and pagination as an ordinary numbered text fallback, not a monospaced inventory, so free-form path entry remains sufficient. Show a plain or monospaced directory listing instead only when the user explicitly requests it or durable user Knowledge establishes that presentation preference. Never preview credential stores, private keys, browser profiles, cookies, tokens, wallets, or other secret-bearing files, and never raise privileges merely to enumerate a path.
|
|
208
|
-
|
|
209
|
-
### Workflows And Actor Runs
|
|
210
|
-
|
|
211
|
-
Keep exact workflow, Recipe, Run, artifact, or task identity visible. Controls may inspect, pause, continue, redirect, retry, or stop only through the owning runtime contract. Never simulate lifecycle state, bypass Control semantics, or treat a generated button as direct execution authority.
|
|
212
|
-
|
|
213
|
-
### Decisions And Design
|
|
214
|
-
|
|
215
|
-
Buttons may represent explicit alternatives without live system inspection. State the decision being made, preserve meaningful trade-offs in visible text, and ensure each prompt records the selected intent rather than silently executing downstream consequences.
|
|
89
|
+
## Failure And Empty States
|
|
216
90
|
|
|
217
|
-
|
|
91
|
+
Show concise failure evidence and emit valid recovery controls such as diagnose, retry, refresh, back, or narrower scope. If a target disappears, return to its nearest valid owner or parent. Empty collections retain the safest useful navigation, inspection, or refinement control rather than degrading to prose-only output.
|
|
218
92
|
|
|
219
|
-
|
|
220
|
-
2. Decide whether the surface needs live, contract, conversational, or adapted evidence.
|
|
221
|
-
3. Inspect only the state required for a truthful projection.
|
|
222
|
-
4. Classify candidate controls by authority and impact.
|
|
223
|
-
5. Render compact state plus context-relevant controls.
|
|
224
|
-
6. On the next turn, interpret the click as a new request and execute only what it authorizes.
|
|
225
|
-
7. Validate the result and regenerate from retained reality.
|
|
93
|
+
## Final Check
|
|
226
94
|
|
|
227
|
-
|
|
95
|
+
Before sending:
|
|
228
96
|
|
|
229
|
-
-
|
|
230
|
-
-
|
|
231
|
-
-
|
|
232
|
-
-
|
|
233
|
-
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
- If the reply asks a Telegram user for bounded confirmation or selection, qualifying controls are present; do not ship a prose-only blocking question merely because the answer is short.
|
|
240
|
-
- If the completed act unblocks a high-confidence next intent inferred from the parent goal and workflow trajectory, qualifying handoff controls are present even when no explicit pending question exists and the latest user message was itself a complete command.
|
|
241
|
-
- State and controls share one clear owner and target.
|
|
242
|
-
- Live claims come from current evidence.
|
|
243
|
-
- Complete versus filtered or adapted output is labeled honestly.
|
|
244
|
-
- No secret appears in visible text or button payloads.
|
|
245
|
-
- Every button carries a valid self-contained next intent and measurably shortens likely feedback.
|
|
246
|
-
- The surface preserves free-form feedback when choices are not exhaustive.
|
|
247
|
-
- High-impact operations route through confirmation.
|
|
248
|
-
- Back/Up and Refresh appear only when useful.
|
|
249
|
-
- The surface remains readable on a mobile screen.
|
|
97
|
+
- At least one useful button is present whenever the transport supports prompt buttons.
|
|
98
|
+
- Every human-readable button label begins with a semantic emoji and one ASCII space.
|
|
99
|
+
- State, actions, owner, and target agree.
|
|
100
|
+
- Live claims are fresh; adaptation and incompleteness are explicit.
|
|
101
|
+
- Every prompt is sufficient and every label follows its semantic emoji rule.
|
|
102
|
+
- Row grouping reflects real hierarchy or peer relationships.
|
|
103
|
+
- High-impact actions require confirmation.
|
|
104
|
+
- No secret or hidden reasoning appears.
|
|
105
|
+
- The surface remains readable on a phone and free-form feedback remains possible.
|