@osolmaz/pi-workflows 0.16.0 → 0.16.2
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/README.md +18 -2
- package/dist/channels/adapter-entry.d.ts +3 -0
- package/dist/channels/adapter-entry.js +203 -0
- package/dist/channels/adapter-entry.js.map +1 -0
- package/dist/channels/config.d.ts +43 -0
- package/dist/channels/config.js +234 -0
- package/dist/channels/config.js.map +1 -0
- package/dist/channels/protocol.d.ts +94 -0
- package/dist/channels/protocol.js +219 -0
- package/dist/channels/protocol.js.map +1 -0
- package/dist/channels/telegram.d.ts +46 -0
- package/dist/channels/telegram.js +285 -0
- package/dist/channels/telegram.js.map +1 -0
- package/dist/client/client.d.ts +1 -0
- package/dist/client/client.js +5 -1
- package/dist/client/client.js.map +1 -1
- package/dist/client/index.d.ts +1 -1
- package/dist/client/protocol.d.ts +1 -1
- package/dist/client/protocol.js +11 -5
- package/dist/client/protocol.js.map +1 -1
- package/dist/client/view.d.ts +48 -16
- package/dist/client/view.js +1 -0
- package/dist/client/view.js.map +1 -1
- package/dist/controllers/index.d.ts +1 -1
- package/dist/controllers/index.js.map +1 -1
- package/dist/controllers/sqlite.d.ts +20 -165
- package/dist/controllers/sqlite.js +178 -436
- package/dist/controllers/sqlite.js.map +1 -1
- package/dist/extension/index.d.ts +23 -2
- package/dist/extension/index.js +637 -534
- package/dist/extension/index.js.map +1 -1
- package/dist/extension/recorder.d.ts +95 -0
- package/dist/extension/recorder.js +530 -0
- package/dist/extension/recorder.js.map +1 -0
- package/dist/extension/remote-recorder-store.d.ts +25 -0
- package/dist/extension/remote-recorder-store.js +81 -0
- package/dist/extension/remote-recorder-store.js.map +1 -0
- package/dist/extension/session-events.d.ts +134 -0
- package/dist/extension/session-events.js +60 -0
- package/dist/extension/session-events.js.map +1 -0
- package/dist/extension/session-view.d.ts +2 -0
- package/dist/extension/session-view.js +60 -2
- package/dist/extension/session-view.js.map +1 -1
- package/dist/extension/step-message.d.ts +6 -4
- package/dist/extension/step-message.js +12 -6
- package/dist/extension/step-message.js.map +1 -1
- package/dist/extension/widget.d.ts +2 -2
- package/dist/extension/widget.js +28 -18
- package/dist/extension/widget.js.map +1 -1
- package/dist/extension/workflow-message-coordinator.d.ts +28 -0
- package/dist/extension/workflow-message-coordinator.js +346 -0
- package/dist/extension/workflow-message-coordinator.js.map +1 -0
- package/dist/host/channel-effects.d.ts +72 -0
- package/dist/host/channel-effects.js +271 -0
- package/dist/host/channel-effects.js.map +1 -0
- package/dist/host/channel-supervisor.d.ts +21 -0
- package/dist/host/channel-supervisor.js +54 -0
- package/dist/host/channel-supervisor.js.map +1 -0
- package/dist/host/runner.d.ts +50 -8
- package/dist/host/runner.js +1632 -341
- package/dist/host/runner.js.map +1 -1
- package/dist/host/state.d.ts +19 -16
- package/dist/host/state.js +251 -63
- package/dist/host/state.js.map +1 -1
- package/dist/host/view.d.ts +19 -9
- package/dist/host/view.js +227 -119
- package/dist/host/view.js.map +1 -1
- package/dist/host/worker-entry.d.ts +4 -1
- package/dist/host/worker-entry.js +23 -24
- package/dist/host/worker-entry.js.map +1 -1
- package/dist/host/worker-protocol.d.ts +15 -0
- package/dist/host/worker-protocol.js.map +1 -1
- package/dist/state/prune.js +3 -25
- package/dist/state/prune.js.map +1 -1
- package/dist/state/schema.js +76 -97
- package/dist/state/schema.js.map +1 -1
- package/dist/state/workflow-messages.d.ts +98 -0
- package/dist/state/workflow-messages.js +366 -0
- package/dist/state/workflow-messages.js.map +1 -0
- package/dist/viewer/render.js +1 -1
- package/dist/viewer/render.js.map +1 -1
- package/dist/viewer/tui.d.ts +1 -1
- package/dist/viewer/tui.js +65 -8
- package/dist/viewer/tui.js.map +1 -1
- package/dist/workflows/composition.js +0 -4
- package/dist/workflows/composition.js.map +1 -1
- package/dist/workflows/definition.js +0 -8
- package/dist/workflows/definition.js.map +1 -1
- package/dist/workflows/engine.js +4 -5
- package/dist/workflows/engine.js.map +1 -1
- package/dist/workflows/human-decision.d.ts +2 -0
- package/dist/workflows/human-decision.js +8 -2
- package/dist/workflows/human-decision.js.map +1 -1
- package/dist/workflows/index.d.ts +1 -1
- package/dist/workflows/index.js.map +1 -1
- package/dist/workflows/schema.js +0 -4
- package/dist/workflows/schema.js.map +1 -1
- package/dist/workflows/settings.d.ts +1 -8
- package/dist/workflows/settings.js.map +1 -1
- package/dist/workflows/store.d.ts +20 -19
- package/dist/workflows/store.js +163 -354
- package/dist/workflows/store.js.map +1 -1
- package/dist/workflows/tool-input.d.ts +21 -0
- package/dist/workflows/tool-input.js +23 -1
- package/dist/workflows/tool-input.js.map +1 -1
- package/dist/workflows/types.d.ts +6 -8
- package/dist/workflows/workflow-message-content.d.ts +38 -0
- package/dist/workflows/workflow-message-content.js +157 -0
- package/dist/workflows/workflow-message-content.js.map +1 -0
- package/docs/2026-08-18-herdr-piw-plan.md +2 -1
- package/docs/2026-08-20-durable-workflow-launch-plan.md +1 -1
- package/docs/2026-08-25-workflow-follow-ups.md +26 -50
- package/docs/2026-08-30-out-of-process-workflow-host-plan.md +3 -3
- package/docs/2026-09-01-restore-session-delivery-controls-plan.md +4 -0
- package/docs/2026-09-01-unified-workflow-client-plan.md +5 -1
- package/docs/2026-09-02-installed-live-e2e-plan.md +15 -1
- package/docs/2026-09-02-unify-workflow-messages-plan.md +562 -0
- package/docs/2026-09-04-workflow-run-state-plan.md +363 -0
- package/docs/DEFERRED_TURNS.md +66 -294
- package/docs/HUMAN_DECISIONS.md +29 -30
- package/docs/HUMAN_DECISION_PRESENTATIONS.md +4 -11
- package/docs/SQLITE_STATE.md +25 -17
- package/docs/WORKFLOW_HOST.md +105 -31
- package/docs/WORKFLOW_STEP_MESSAGES.md +166 -75
- package/docs/live-replay-protocol.md +8 -4
- package/docs/tui-viewer.md +3 -1
- package/docs/workflows.md +44 -28
- package/herdr-plugin.toml +1 -1
- package/package.json +1 -1
- package/plugins/herdr/viewer.mjs +14 -5
- package/src/channels/adapter-entry.ts +220 -0
- package/src/channels/config.ts +296 -0
- package/src/channels/protocol.ts +333 -0
- package/src/channels/telegram.ts +335 -0
- package/src/client/client.ts +6 -2
- package/src/client/index.ts +2 -1
- package/src/client/protocol.ts +11 -5
- package/src/client/view.ts +51 -18
- package/src/controllers/index.ts +0 -1
- package/src/controllers/sqlite.ts +247 -845
- package/src/extension/index.ts +712 -647
- package/src/extension/recorder.ts +687 -0
- package/src/extension/remote-recorder-store.ts +126 -0
- package/src/extension/session-events.ts +119 -0
- package/src/extension/session-view.ts +86 -3
- package/src/extension/step-message.ts +19 -9
- package/src/extension/widget.ts +37 -17
- package/src/extension/workflow-message-coordinator.ts +398 -0
- package/src/host/channel-effects.ts +465 -0
- package/src/host/channel-supervisor.ts +73 -0
- package/src/host/runner.ts +2163 -525
- package/src/host/state.ts +333 -94
- package/src/host/view.ts +254 -122
- package/src/host/worker-entry.ts +38 -30
- package/src/host/worker-protocol.ts +11 -0
- package/src/state/prune.ts +3 -31
- package/src/state/schema.ts +76 -97
- package/src/state/workflow-messages.ts +599 -0
- package/src/viewer/render.ts +1 -5
- package/src/viewer/tui.ts +71 -6
- package/src/workflows/composition.ts +0 -5
- package/src/workflows/definition.ts +0 -8
- package/src/workflows/engine.ts +4 -6
- package/src/workflows/human-decision.ts +18 -2
- package/src/workflows/index.ts +0 -1
- package/src/workflows/schema.ts +0 -6
- package/src/workflows/settings.ts +1 -20
- package/src/workflows/store.ts +237 -489
- package/src/workflows/tool-input.ts +36 -1
- package/src/workflows/types.ts +6 -8
- package/src/workflows/workflow-message-content.ts +197 -0
- package/dist/extension/decision-channels.d.ts +0 -134
- package/dist/extension/decision-channels.js +0 -1307
- package/dist/extension/decision-channels.js.map +0 -1
- package/src/extension/decision-channels.ts +0 -1826
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
export const CHANNEL_ADAPTER_PROTOCOL_SCHEMA = "pi-workflows.channel-adapter.v1";
|
|
3
|
+
export function encodeChannelLine(value) {
|
|
4
|
+
return Buffer.from(`${JSON.stringify(value)}\n`, "utf8");
|
|
5
|
+
}
|
|
6
|
+
export function parseChannelAdapterMessage(frame) {
|
|
7
|
+
const value = parseObject(frame, "channel adapter message");
|
|
8
|
+
requireBase(value);
|
|
9
|
+
const kind = value.kind;
|
|
10
|
+
if (kind === "channel.ready" || kind === "channel.exiting") {
|
|
11
|
+
requireNonNegativeInteger(value.cursor, "channel cursor");
|
|
12
|
+
}
|
|
13
|
+
else if (kind === "channel.present") {
|
|
14
|
+
requireText(value.decisionId, "decisionId");
|
|
15
|
+
requireText(value.requestDigest, "requestDigest");
|
|
16
|
+
requireText(value.attemptId, "attemptId");
|
|
17
|
+
requireOneOf(value.state, ["confirmed", "failed", "unknown"], "presentation state");
|
|
18
|
+
if (!Array.isArray(value.messages))
|
|
19
|
+
throw new Error("Channel message references are invalid");
|
|
20
|
+
value.messages.forEach(validateMessageReference);
|
|
21
|
+
requireOptionalText(value.errorCode, "errorCode");
|
|
22
|
+
}
|
|
23
|
+
else if (kind === "channel.answer") {
|
|
24
|
+
requireText(value.decisionId, "decisionId");
|
|
25
|
+
requireText(value.requestDigest, "requestDigest");
|
|
26
|
+
validateDecisionResponse(value.response);
|
|
27
|
+
requireText(value.actorId, "actorId");
|
|
28
|
+
requireText(value.chatId, "chatId");
|
|
29
|
+
requireText(value.eventId, "eventId");
|
|
30
|
+
requireText(value.idempotencyKey, "idempotencyKey");
|
|
31
|
+
requireNonNegativeInteger(value.cursor, "channel cursor");
|
|
32
|
+
}
|
|
33
|
+
else if (kind === "channel.settle") {
|
|
34
|
+
requireText(value.decisionId, "decisionId");
|
|
35
|
+
requireText(value.requestDigest, "requestDigest");
|
|
36
|
+
requireText(value.attemptId, "attemptId");
|
|
37
|
+
requireOneOf(value.state, ["confirmed", "failed", "unknown"], "settlement state");
|
|
38
|
+
requireOptionalText(value.errorCode, "errorCode");
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
throw new Error("Channel adapter message kind is invalid");
|
|
42
|
+
}
|
|
43
|
+
return value;
|
|
44
|
+
}
|
|
45
|
+
export function parseChannelAdapterResponse(frame) {
|
|
46
|
+
const value = parseObject(frame, "channel adapter response");
|
|
47
|
+
if (value.schema !== CHANNEL_ADAPTER_PROTOCOL_SCHEMA ||
|
|
48
|
+
value.type !== "response" ||
|
|
49
|
+
!Number.isSafeInteger(value.sequence) ||
|
|
50
|
+
(value.outcome !== "accepted" && value.outcome !== "rejected") ||
|
|
51
|
+
!Number.isSafeInteger(value.revision)) {
|
|
52
|
+
throw new Error("Channel adapter response is invalid");
|
|
53
|
+
}
|
|
54
|
+
requirePositiveInteger(value.sequence, "channel response sequence");
|
|
55
|
+
requireNonNegativeInteger(value.revision, "channel response revision");
|
|
56
|
+
requireOptionalText(value.error, "channel response error");
|
|
57
|
+
validateCommand(value.command);
|
|
58
|
+
return value;
|
|
59
|
+
}
|
|
60
|
+
export function parseChannelAdapterLaunch(value) {
|
|
61
|
+
const launch = requireObject(value, "channel adapter launch envelope");
|
|
62
|
+
if (launch.schema !== "pi-workflows.channel-adapter-launch.v1") {
|
|
63
|
+
throw new Error("Channel adapter launch envelope is invalid");
|
|
64
|
+
}
|
|
65
|
+
requireText(launch.adapterEpoch, "adapterEpoch");
|
|
66
|
+
requireText(launch.profile, "profile");
|
|
67
|
+
requireText(launch.token, "token");
|
|
68
|
+
requireStringArray(launch.allowedUserIds, "allowedUserIds");
|
|
69
|
+
requireStringArray(launch.allowedChatIds, "allowedChatIds");
|
|
70
|
+
requireOptionalText(launch.apiBase, "apiBase");
|
|
71
|
+
return launch;
|
|
72
|
+
}
|
|
73
|
+
export function channelResponse(message, outcome, revision, command, error) {
|
|
74
|
+
return {
|
|
75
|
+
schema: CHANNEL_ADAPTER_PROTOCOL_SCHEMA,
|
|
76
|
+
type: "response",
|
|
77
|
+
sequence: message.sequence,
|
|
78
|
+
outcome,
|
|
79
|
+
revision,
|
|
80
|
+
command,
|
|
81
|
+
...(error === undefined ? {} : { error }),
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
export function channelStableMessageId(parts) {
|
|
85
|
+
return `channel-${createHash("sha256").update(parts.join("\0")).digest("hex")}`;
|
|
86
|
+
}
|
|
87
|
+
function requireBase(value) {
|
|
88
|
+
if (value.schema !== CHANNEL_ADAPTER_PROTOCOL_SCHEMA) {
|
|
89
|
+
throw new Error("Channel adapter message is invalid");
|
|
90
|
+
}
|
|
91
|
+
requireText(value.adapterEpoch, "adapterEpoch");
|
|
92
|
+
requireText(value.profile, "profile");
|
|
93
|
+
requirePositiveInteger(value.sequence, "channel sequence");
|
|
94
|
+
requireNonNegativeInteger(value.expectedRevision, "channel expected revision");
|
|
95
|
+
requireText(value.stableMessageId, "stableMessageId");
|
|
96
|
+
}
|
|
97
|
+
function validateCommand(value) {
|
|
98
|
+
if (value === null)
|
|
99
|
+
return;
|
|
100
|
+
const command = requireObject(value, "channel command");
|
|
101
|
+
if (command.kind === "channel.stop")
|
|
102
|
+
return;
|
|
103
|
+
if (command.kind === "channel.present") {
|
|
104
|
+
requireText(command.stableMessageId, "stableMessageId");
|
|
105
|
+
requireText(command.attemptId, "attemptId");
|
|
106
|
+
validateChannelRequest(command.request);
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
if (command.kind === "channel.settle") {
|
|
110
|
+
requireText(command.stableMessageId, "stableMessageId");
|
|
111
|
+
requireText(command.attemptId, "attemptId");
|
|
112
|
+
validateChannelRequest(command.request);
|
|
113
|
+
requireOneOf(command.outcome, ["accepted", "cancelled", "expired"], "settlement outcome");
|
|
114
|
+
if (command.response !== undefined)
|
|
115
|
+
validateDecisionResponse(command.response);
|
|
116
|
+
if (!Array.isArray(command.messages))
|
|
117
|
+
throw new Error("Channel message references are invalid");
|
|
118
|
+
command.messages.forEach(validateMessageReference);
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
if (command.kind === "channel.poll") {
|
|
122
|
+
requireNonNegativeInteger(command.cursor, "channel cursor");
|
|
123
|
+
if (!Array.isArray(command.requests))
|
|
124
|
+
throw new Error("Channel poll requests are invalid");
|
|
125
|
+
command.requests.forEach(validateChannelRequest);
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
throw new Error("Channel adapter command kind is invalid");
|
|
129
|
+
}
|
|
130
|
+
function validateChannelRequest(value) {
|
|
131
|
+
const request = requireObject(value, "human decision channel request");
|
|
132
|
+
if (request.schema !== "pi-workflows.human-decision-channel-request.v1" ||
|
|
133
|
+
request.sourceSchema !== "pi-workflows.human-decision-request.v1" ||
|
|
134
|
+
Object.hasOwn(request, "subject")) {
|
|
135
|
+
throw new Error("Human decision channel request is invalid");
|
|
136
|
+
}
|
|
137
|
+
for (const field of [
|
|
138
|
+
"decisionId",
|
|
139
|
+
"requestDigest",
|
|
140
|
+
"runId",
|
|
141
|
+
"workflowName",
|
|
142
|
+
"nodeId",
|
|
143
|
+
"attemptId",
|
|
144
|
+
"audience",
|
|
145
|
+
"title",
|
|
146
|
+
"presentationDigest",
|
|
147
|
+
"createdAt",
|
|
148
|
+
]) {
|
|
149
|
+
requireText(request[field], field);
|
|
150
|
+
}
|
|
151
|
+
requireNonNegativeInteger(request.revision, "decision revision");
|
|
152
|
+
requireObject(request.presentation, "decision presentation");
|
|
153
|
+
requireObject(request.choices, "decision choices");
|
|
154
|
+
requireOptionalText(request.expiresAt, "decision expiry");
|
|
155
|
+
if (request.defaultResponse !== undefined)
|
|
156
|
+
validateDecisionResponse(request.defaultResponse);
|
|
157
|
+
}
|
|
158
|
+
function validateDecisionResponse(value) {
|
|
159
|
+
const response = requireObject(value, "human decision response");
|
|
160
|
+
requireText(response.choice, "decision choice");
|
|
161
|
+
if (response.input === undefined)
|
|
162
|
+
return;
|
|
163
|
+
const input = requireObject(response.input, "decision input");
|
|
164
|
+
if (Object.values(input).some((item) => typeof item !== "string")) {
|
|
165
|
+
throw new Error("Decision input values must be strings");
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
function validateMessageReference(value) {
|
|
169
|
+
const reference = requireObject(value, "Telegram message reference");
|
|
170
|
+
requireText(reference.chatId, "Telegram chat ID");
|
|
171
|
+
requireText(reference.messageId, "Telegram message ID");
|
|
172
|
+
requireNonNegativeInteger(reference.recipientIndex, "Telegram recipient index");
|
|
173
|
+
requireNonNegativeInteger(reference.partIndex, "Telegram part index");
|
|
174
|
+
requireText(reference.contentDigest, "Telegram content digest");
|
|
175
|
+
}
|
|
176
|
+
function requireObject(value, label) {
|
|
177
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) {
|
|
178
|
+
throw new Error(`${label} must be an object`);
|
|
179
|
+
}
|
|
180
|
+
return value;
|
|
181
|
+
}
|
|
182
|
+
function requireText(value, label) {
|
|
183
|
+
if (typeof value !== "string" || value.length === 0)
|
|
184
|
+
throw new Error(`${label} is invalid`);
|
|
185
|
+
}
|
|
186
|
+
function requireOptionalText(value, label) {
|
|
187
|
+
if (value !== undefined)
|
|
188
|
+
requireText(value, label);
|
|
189
|
+
}
|
|
190
|
+
function requirePositiveInteger(value, label) {
|
|
191
|
+
if (!Number.isSafeInteger(value) || value <= 0)
|
|
192
|
+
throw new Error(`${label} is invalid`);
|
|
193
|
+
}
|
|
194
|
+
function requireNonNegativeInteger(value, label) {
|
|
195
|
+
if (!Number.isSafeInteger(value) || value < 0)
|
|
196
|
+
throw new Error(`${label} is invalid`);
|
|
197
|
+
}
|
|
198
|
+
function requireStringArray(value, label) {
|
|
199
|
+
if (!Array.isArray(value) ||
|
|
200
|
+
value.length === 0 ||
|
|
201
|
+
value.some((item) => typeof item !== "string" || item.length === 0)) {
|
|
202
|
+
throw new Error(`${label} is invalid`);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
function requireOneOf(value, allowed, label) {
|
|
206
|
+
if (typeof value !== "string" || !allowed.includes(value))
|
|
207
|
+
throw new Error(`${label} is invalid`);
|
|
208
|
+
}
|
|
209
|
+
function parseObject(frame, label) {
|
|
210
|
+
let value;
|
|
211
|
+
try {
|
|
212
|
+
value = JSON.parse(frame.toString("utf8"));
|
|
213
|
+
}
|
|
214
|
+
catch {
|
|
215
|
+
throw new Error(`${label} is not valid JSON`);
|
|
216
|
+
}
|
|
217
|
+
return requireObject(value, label);
|
|
218
|
+
}
|
|
219
|
+
//# sourceMappingURL=protocol.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"protocol.js","sourceRoot":"","sources":["../../src/channels/protocol.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { HumanDecisionChannelRequest, HumanDecisionResponse } from "../workflows/types.js";
|
|
2
|
+
import type { TelegramFetch } from "./config.js";
|
|
3
|
+
import type { TelegramMessageReference } from "./protocol.js";
|
|
4
|
+
export type TelegramVerifiedAnswer = {
|
|
5
|
+
request: HumanDecisionChannelRequest;
|
|
6
|
+
response: HumanDecisionResponse;
|
|
7
|
+
actorId: string;
|
|
8
|
+
chatId: string;
|
|
9
|
+
eventId: string;
|
|
10
|
+
cursor: number;
|
|
11
|
+
};
|
|
12
|
+
export declare class TelegramAdapter {
|
|
13
|
+
private readonly options;
|
|
14
|
+
private requests;
|
|
15
|
+
private readonly allowedUsers;
|
|
16
|
+
private readonly allowedChats;
|
|
17
|
+
private readonly request;
|
|
18
|
+
constructor(options: {
|
|
19
|
+
profile: string;
|
|
20
|
+
token: string;
|
|
21
|
+
allowedUserIds: readonly string[];
|
|
22
|
+
allowedChatIds: readonly string[];
|
|
23
|
+
fetchFn?: TelegramFetch;
|
|
24
|
+
apiBase?: string;
|
|
25
|
+
});
|
|
26
|
+
setRequests(requests: readonly HumanDecisionChannelRequest[]): void;
|
|
27
|
+
present(request: HumanDecisionChannelRequest): Promise<TelegramMessageReference[]>;
|
|
28
|
+
poll(cursor: number): Promise<{
|
|
29
|
+
cursor: number;
|
|
30
|
+
answers: TelegramVerifiedAnswer[];
|
|
31
|
+
}>;
|
|
32
|
+
settle(outcome: "accepted" | "cancelled" | "expired", response: HumanDecisionResponse | undefined, messages: readonly TelegramMessageReference[]): Promise<void>;
|
|
33
|
+
private handleUpdate;
|
|
34
|
+
private handleCallback;
|
|
35
|
+
private handleReply;
|
|
36
|
+
private keyboard;
|
|
37
|
+
private callbackBinding;
|
|
38
|
+
private replyBinding;
|
|
39
|
+
private callbackToken;
|
|
40
|
+
private replyToken;
|
|
41
|
+
private token;
|
|
42
|
+
private answerCallback;
|
|
43
|
+
private call;
|
|
44
|
+
}
|
|
45
|
+
export declare function renderDecisionText(request: HumanDecisionChannelRequest): string;
|
|
46
|
+
export declare function renderTelegramParts(request: HumanDecisionChannelRequest): string[];
|
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
import { createHmac } from "node:crypto";
|
|
2
|
+
import { decisionDocumentSegments, digestCanonical } from "../workflows/decision-presentation.js";
|
|
3
|
+
const DEFAULT_API_BASE = "https://api.telegram.org";
|
|
4
|
+
const TELEGRAM_TEXT_LIMIT = 4_096;
|
|
5
|
+
const CALLBACK_PREFIX = "pw:";
|
|
6
|
+
const REPLY_TOKEN_PREFIX = "Reply token: ";
|
|
7
|
+
export class TelegramAdapter {
|
|
8
|
+
options;
|
|
9
|
+
requests = [];
|
|
10
|
+
allowedUsers;
|
|
11
|
+
allowedChats;
|
|
12
|
+
request;
|
|
13
|
+
constructor(options) {
|
|
14
|
+
this.options = options;
|
|
15
|
+
this.allowedUsers = new Set(options.allowedUserIds);
|
|
16
|
+
this.allowedChats = new Set(options.allowedChatIds);
|
|
17
|
+
this.request = options.fetchFn ?? fetch;
|
|
18
|
+
}
|
|
19
|
+
setRequests(requests) {
|
|
20
|
+
this.requests = [...requests];
|
|
21
|
+
}
|
|
22
|
+
async present(request) {
|
|
23
|
+
const parts = renderTelegramParts(request);
|
|
24
|
+
const references = [];
|
|
25
|
+
const keyboard = this.keyboard(request);
|
|
26
|
+
for (const [recipientIndex, chatId] of [...this.allowedChats].entries()) {
|
|
27
|
+
for (const [partIndex, text] of parts.entries()) {
|
|
28
|
+
const result = await this.call("sendMessage", {
|
|
29
|
+
chat_id: chatId,
|
|
30
|
+
text,
|
|
31
|
+
...(partIndex === parts.length - 1
|
|
32
|
+
? { reply_markup: { inline_keyboard: keyboard } }
|
|
33
|
+
: {}),
|
|
34
|
+
});
|
|
35
|
+
const messageId = integerField(result, "message_id", "Telegram sendMessage result");
|
|
36
|
+
references.push({
|
|
37
|
+
chatId,
|
|
38
|
+
messageId: String(messageId),
|
|
39
|
+
recipientIndex,
|
|
40
|
+
partIndex,
|
|
41
|
+
contentDigest: digestCanonical(text),
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return references;
|
|
46
|
+
}
|
|
47
|
+
async poll(cursor) {
|
|
48
|
+
const result = await this.call("getUpdates", {
|
|
49
|
+
offset: cursor,
|
|
50
|
+
timeout: 1,
|
|
51
|
+
allowed_updates: ["callback_query", "message"],
|
|
52
|
+
});
|
|
53
|
+
if (!Array.isArray(result))
|
|
54
|
+
throw new Error("Telegram getUpdates result must be an array");
|
|
55
|
+
let nextCursor = cursor;
|
|
56
|
+
const answers = [];
|
|
57
|
+
for (const raw of result) {
|
|
58
|
+
const update = asRecord(raw);
|
|
59
|
+
if (update === null || !Number.isSafeInteger(update.update_id))
|
|
60
|
+
continue;
|
|
61
|
+
const updateId = update.update_id;
|
|
62
|
+
nextCursor = Math.max(nextCursor, updateId + 1);
|
|
63
|
+
const answer = await this.handleUpdate(update, updateId + 1);
|
|
64
|
+
if (answer !== undefined)
|
|
65
|
+
answers.push(answer);
|
|
66
|
+
}
|
|
67
|
+
return { cursor: nextCursor, answers };
|
|
68
|
+
}
|
|
69
|
+
async settle(outcome, response, messages) {
|
|
70
|
+
const seenChats = new Set();
|
|
71
|
+
for (const message of messages) {
|
|
72
|
+
await this.call("editMessageReplyMarkup", {
|
|
73
|
+
chat_id: message.chatId,
|
|
74
|
+
message_id: Number.parseInt(message.messageId, 10),
|
|
75
|
+
reply_markup: { inline_keyboard: [] },
|
|
76
|
+
});
|
|
77
|
+
if (seenChats.has(message.chatId))
|
|
78
|
+
continue;
|
|
79
|
+
seenChats.add(message.chatId);
|
|
80
|
+
const selection = response?.choice === undefined ? "" : ` (${response.choice})`;
|
|
81
|
+
await this.call("sendMessage", {
|
|
82
|
+
chat_id: message.chatId,
|
|
83
|
+
text: `Decision ${outcome}${selection}.`,
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
async handleUpdate(update, cursor) {
|
|
88
|
+
const callback = asRecord(update.callback_query);
|
|
89
|
+
if (callback !== null)
|
|
90
|
+
return await this.handleCallback(callback, cursor);
|
|
91
|
+
const message = asRecord(update.message);
|
|
92
|
+
if (message !== null)
|
|
93
|
+
return await this.handleReply(message, cursor);
|
|
94
|
+
return undefined;
|
|
95
|
+
}
|
|
96
|
+
async handleCallback(callback, cursor) {
|
|
97
|
+
const callbackId = stringField(callback, "id");
|
|
98
|
+
const actor = asRecord(callback.from);
|
|
99
|
+
const message = asRecord(callback.message);
|
|
100
|
+
const chat = asRecord(message?.chat);
|
|
101
|
+
const actorId = numericText(actor?.id);
|
|
102
|
+
const chatId = numericText(chat?.id);
|
|
103
|
+
const data = typeof callback.data === "string" ? callback.data : "";
|
|
104
|
+
if (callbackId === undefined ||
|
|
105
|
+
actorId === undefined ||
|
|
106
|
+
chatId === undefined ||
|
|
107
|
+
!this.allowedUsers.has(actorId) ||
|
|
108
|
+
!this.allowedChats.has(chatId)) {
|
|
109
|
+
if (callbackId !== undefined) {
|
|
110
|
+
await this.answerCallback(callbackId, "This decision answer is not authorized.");
|
|
111
|
+
}
|
|
112
|
+
return undefined;
|
|
113
|
+
}
|
|
114
|
+
const binding = this.callbackBinding(data);
|
|
115
|
+
if (binding === undefined) {
|
|
116
|
+
await this.answerCallback(callbackId, "This decision choice is no longer active.");
|
|
117
|
+
return undefined;
|
|
118
|
+
}
|
|
119
|
+
const choice = binding.request.choices[binding.choice];
|
|
120
|
+
if (choice === undefined)
|
|
121
|
+
return undefined;
|
|
122
|
+
if (choice.input !== undefined) {
|
|
123
|
+
const token = this.replyToken(binding.request, binding.choice);
|
|
124
|
+
await this.call("sendMessage", {
|
|
125
|
+
chat_id: chatId,
|
|
126
|
+
text: `${choice.input.prompt}\n${REPLY_TOKEN_PREFIX}${token}`,
|
|
127
|
+
reply_markup: { force_reply: true, selective: true },
|
|
128
|
+
});
|
|
129
|
+
await this.answerCallback(callbackId, "Reply to the new prompt.");
|
|
130
|
+
return undefined;
|
|
131
|
+
}
|
|
132
|
+
await this.answerCallback(callbackId, "Answer received.");
|
|
133
|
+
return {
|
|
134
|
+
request: binding.request,
|
|
135
|
+
response: { choice: binding.choice },
|
|
136
|
+
actorId,
|
|
137
|
+
chatId,
|
|
138
|
+
eventId: callbackId,
|
|
139
|
+
cursor,
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
async handleReply(message, cursor) {
|
|
143
|
+
const actorId = numericText(asRecord(message.from)?.id);
|
|
144
|
+
const chatId = numericText(asRecord(message.chat)?.id);
|
|
145
|
+
const text = typeof message.text === "string" ? message.text.trim() : "";
|
|
146
|
+
const replyText = asRecord(message.reply_to_message)?.text;
|
|
147
|
+
const eventId = numericText(message.message_id);
|
|
148
|
+
if (actorId === undefined ||
|
|
149
|
+
chatId === undefined ||
|
|
150
|
+
eventId === undefined ||
|
|
151
|
+
text.length === 0 ||
|
|
152
|
+
typeof replyText !== "string" ||
|
|
153
|
+
!this.allowedUsers.has(actorId) ||
|
|
154
|
+
!this.allowedChats.has(chatId)) {
|
|
155
|
+
return undefined;
|
|
156
|
+
}
|
|
157
|
+
const marker = replyText.lastIndexOf(REPLY_TOKEN_PREFIX);
|
|
158
|
+
if (marker < 0)
|
|
159
|
+
return undefined;
|
|
160
|
+
const token = replyText
|
|
161
|
+
.slice(marker + REPLY_TOKEN_PREFIX.length)
|
|
162
|
+
.trim()
|
|
163
|
+
.split(/\s/u)[0];
|
|
164
|
+
if (token === undefined)
|
|
165
|
+
return undefined;
|
|
166
|
+
const binding = this.replyBinding(token);
|
|
167
|
+
if (binding === undefined)
|
|
168
|
+
return undefined;
|
|
169
|
+
const choice = binding.request.choices[binding.choice];
|
|
170
|
+
if (choice?.input === undefined)
|
|
171
|
+
return undefined;
|
|
172
|
+
return {
|
|
173
|
+
request: binding.request,
|
|
174
|
+
response: { choice: binding.choice, input: { [choice.input.name]: text } },
|
|
175
|
+
actorId,
|
|
176
|
+
chatId,
|
|
177
|
+
eventId,
|
|
178
|
+
cursor,
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
keyboard(request) {
|
|
182
|
+
return Object.entries(request.choices).map(([choice, definition]) => [
|
|
183
|
+
{
|
|
184
|
+
text: definition.label,
|
|
185
|
+
callback_data: `${CALLBACK_PREFIX}${this.callbackToken(request, choice)}`,
|
|
186
|
+
},
|
|
187
|
+
]);
|
|
188
|
+
}
|
|
189
|
+
callbackBinding(data) {
|
|
190
|
+
if (!data.startsWith(CALLBACK_PREFIX))
|
|
191
|
+
return undefined;
|
|
192
|
+
const token = data.slice(CALLBACK_PREFIX.length);
|
|
193
|
+
for (const request of this.requests) {
|
|
194
|
+
for (const choice of Object.keys(request.choices)) {
|
|
195
|
+
if (this.callbackToken(request, choice) === token)
|
|
196
|
+
return { request, choice };
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
return undefined;
|
|
200
|
+
}
|
|
201
|
+
replyBinding(token) {
|
|
202
|
+
for (const request of this.requests) {
|
|
203
|
+
for (const [choice, definition] of Object.entries(request.choices)) {
|
|
204
|
+
if (definition.input !== undefined && this.replyToken(request, choice) === token) {
|
|
205
|
+
return { request, choice };
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
return undefined;
|
|
210
|
+
}
|
|
211
|
+
callbackToken(request, choice) {
|
|
212
|
+
return this.token("callback", request, choice);
|
|
213
|
+
}
|
|
214
|
+
replyToken(request, choice) {
|
|
215
|
+
return this.token("reply", request, choice);
|
|
216
|
+
}
|
|
217
|
+
token(purpose, request, choice) {
|
|
218
|
+
return createHmac("sha256", this.options.token)
|
|
219
|
+
.update(`${purpose}\0${this.options.profile}\0${request.requestDigest}\0${choice}`)
|
|
220
|
+
.digest("base64url")
|
|
221
|
+
.slice(0, 32);
|
|
222
|
+
}
|
|
223
|
+
async answerCallback(callbackQueryId, text) {
|
|
224
|
+
await this.call("answerCallbackQuery", { callback_query_id: callbackQueryId, text });
|
|
225
|
+
}
|
|
226
|
+
async call(method, payload) {
|
|
227
|
+
const apiBase = this.options.apiBase ?? DEFAULT_API_BASE;
|
|
228
|
+
const response = await this.request(`${apiBase}/bot${encodeURIComponent(this.options.token)}/${method}`, {
|
|
229
|
+
method: "POST",
|
|
230
|
+
headers: { "content-type": "application/json" },
|
|
231
|
+
body: JSON.stringify(payload),
|
|
232
|
+
});
|
|
233
|
+
if (!response.ok)
|
|
234
|
+
throw new Error(`Telegram ${method} failed with HTTP ${response.status}`);
|
|
235
|
+
const body = asRecord(await response.json());
|
|
236
|
+
if (body?.ok !== true)
|
|
237
|
+
throw new Error(`Telegram ${method} was rejected`);
|
|
238
|
+
return body.result;
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
export function renderDecisionText(request) {
|
|
242
|
+
return decisionDocumentSegments(request)
|
|
243
|
+
.map((segment) => segment.text)
|
|
244
|
+
.join("\n\n");
|
|
245
|
+
}
|
|
246
|
+
export function renderTelegramParts(request) {
|
|
247
|
+
const text = renderDecisionText(request);
|
|
248
|
+
if (text.length <= TELEGRAM_TEXT_LIMIT)
|
|
249
|
+
return [text];
|
|
250
|
+
const parts = [];
|
|
251
|
+
let remaining = text;
|
|
252
|
+
while (remaining.length > TELEGRAM_TEXT_LIMIT) {
|
|
253
|
+
const window = remaining.slice(0, TELEGRAM_TEXT_LIMIT);
|
|
254
|
+
const boundary = Math.max(window.lastIndexOf("\n\n"), window.lastIndexOf("\n"));
|
|
255
|
+
const cut = boundary > TELEGRAM_TEXT_LIMIT / 2 ? boundary : TELEGRAM_TEXT_LIMIT;
|
|
256
|
+
parts.push(remaining.slice(0, cut));
|
|
257
|
+
remaining = remaining.slice(cut).replace(/^\n+/u, "");
|
|
258
|
+
}
|
|
259
|
+
if (remaining.length > 0)
|
|
260
|
+
parts.push(remaining);
|
|
261
|
+
return parts;
|
|
262
|
+
}
|
|
263
|
+
function integerField(value, field, label) {
|
|
264
|
+
const record = asRecord(value);
|
|
265
|
+
const result = record?.[field];
|
|
266
|
+
if (!Number.isSafeInteger(result))
|
|
267
|
+
throw new Error(`${label} ${field} must be an integer`);
|
|
268
|
+
return result;
|
|
269
|
+
}
|
|
270
|
+
function stringField(value, field) {
|
|
271
|
+
return typeof value[field] === "string" ? value[field] : undefined;
|
|
272
|
+
}
|
|
273
|
+
function numericText(value) {
|
|
274
|
+
if (typeof value === "number" && Number.isSafeInteger(value))
|
|
275
|
+
return String(value);
|
|
276
|
+
if (typeof value === "string" && /^-?[0-9]+$/u.test(value))
|
|
277
|
+
return value;
|
|
278
|
+
return undefined;
|
|
279
|
+
}
|
|
280
|
+
function asRecord(value) {
|
|
281
|
+
return value !== null && typeof value === "object" && !Array.isArray(value)
|
|
282
|
+
? value
|
|
283
|
+
: null;
|
|
284
|
+
}
|
|
285
|
+
//# sourceMappingURL=telegram.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"telegram.js","sourceRoot":"","sources":["../../src/channels/telegram.ts"],"names":[],"mappings":"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"}
|
package/dist/client/client.d.ts
CHANGED
|
@@ -57,6 +57,7 @@ export declare class WorkflowClient {
|
|
|
57
57
|
}): Promise<() => Promise<void>>;
|
|
58
58
|
watchSession(sessionId: string, listener: (event: ClientEvent) => void, options?: {
|
|
59
59
|
subscriptionId?: string;
|
|
60
|
+
coordinator?: boolean;
|
|
60
61
|
}): Promise<() => Promise<void>>;
|
|
61
62
|
ensureAvailable(): Promise<ClientHello>;
|
|
62
63
|
ensureRunning(): Promise<ClientResponse>;
|
package/dist/client/client.js
CHANGED
|
@@ -99,7 +99,11 @@ export class WorkflowClient {
|
|
|
99
99
|
}, listener);
|
|
100
100
|
}
|
|
101
101
|
async watchSession(sessionId, listener, options = {}) {
|
|
102
|
-
return await this.subscribe("view.session.watch", undefined, {
|
|
102
|
+
return await this.subscribe("view.session.watch", undefined, {
|
|
103
|
+
subscriptionId: options.subscriptionId ?? randomUUID(),
|
|
104
|
+
sessionId,
|
|
105
|
+
...(options.coordinator === undefined ? {} : { coordinator: options.coordinator }),
|
|
106
|
+
}, listener);
|
|
103
107
|
}
|
|
104
108
|
async ensureAvailable() {
|
|
105
109
|
try {
|