@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
|
@@ -12,7 +12,8 @@ const inputSchema = Type.Unknown({
|
|
|
12
12
|
"Ordinary checkpoint answer for answer; protected human decisions require a human channel; optional structured workflow input for start",
|
|
13
13
|
});
|
|
14
14
|
const runIdSchema = Type.String({
|
|
15
|
-
description:
|
|
15
|
+
description:
|
|
16
|
+
"Run id; required for restart and optional for status, cancel, answer, settings, and follow-ups",
|
|
16
17
|
});
|
|
17
18
|
const stepSchema = Type.String({
|
|
18
19
|
description: "Workflow step id; required when action is update or submit",
|
|
@@ -44,6 +45,33 @@ export const WorkflowActionSchemas = {
|
|
|
44
45
|
},
|
|
45
46
|
noExtraProperties,
|
|
46
47
|
),
|
|
48
|
+
restart: Type.Object({ action: Type.Literal("restart"), runId: runIdSchema }, noExtraProperties),
|
|
49
|
+
"change-settings": Type.Object(
|
|
50
|
+
{
|
|
51
|
+
action: Type.Literal("change-settings"),
|
|
52
|
+
runId: Type.Optional(runIdSchema),
|
|
53
|
+
scopeId: Type.Optional(Type.String()),
|
|
54
|
+
expectedChangeNumber: Type.Optional(Type.Integer({ minimum: 0 })),
|
|
55
|
+
patch: Type.Unknown(),
|
|
56
|
+
},
|
|
57
|
+
noExtraProperties,
|
|
58
|
+
),
|
|
59
|
+
"queue-follow-up": Type.Object(
|
|
60
|
+
{
|
|
61
|
+
action: Type.Literal("queue-follow-up"),
|
|
62
|
+
runId: Type.Optional(runIdSchema),
|
|
63
|
+
prompt: Type.String({ minLength: 1 }),
|
|
64
|
+
},
|
|
65
|
+
noExtraProperties,
|
|
66
|
+
),
|
|
67
|
+
"remove-follow-up": Type.Object(
|
|
68
|
+
{
|
|
69
|
+
action: Type.Literal("remove-follow-up"),
|
|
70
|
+
runId: Type.Optional(runIdSchema),
|
|
71
|
+
followUpId: Type.String(),
|
|
72
|
+
},
|
|
73
|
+
noExtraProperties,
|
|
74
|
+
),
|
|
47
75
|
status: Type.Object(
|
|
48
76
|
{ action: Type.Literal("status"), runId: Type.Optional(runIdSchema) },
|
|
49
77
|
noExtraProperties,
|
|
@@ -102,6 +130,13 @@ type ToolInputParser<Output> = (value: unknown) => Output;
|
|
|
102
130
|
const workflowInputParsers = {
|
|
103
131
|
list: (value) => parseToolInput(WorkflowActionSchemas.list, value, "workflow"),
|
|
104
132
|
start: (value) => parseToolInput(WorkflowActionSchemas.start, value, "workflow"),
|
|
133
|
+
restart: (value) => parseToolInput(WorkflowActionSchemas.restart, value, "workflow"),
|
|
134
|
+
"change-settings": (value) =>
|
|
135
|
+
parseToolInput(WorkflowActionSchemas["change-settings"], value, "workflow"),
|
|
136
|
+
"queue-follow-up": (value) =>
|
|
137
|
+
parseToolInput(WorkflowActionSchemas["queue-follow-up"], value, "workflow"),
|
|
138
|
+
"remove-follow-up": (value) =>
|
|
139
|
+
parseToolInput(WorkflowActionSchemas["remove-follow-up"], value, "workflow"),
|
|
105
140
|
status: (value) => parseToolInput(WorkflowActionSchemas.status, value, "workflow"),
|
|
106
141
|
pause: (value) => parseToolInput(WorkflowActionSchemas.pause, value, "workflow"),
|
|
107
142
|
resume: (value) => parseToolInput(WorkflowActionSchemas.resume, value, "workflow"),
|
package/src/workflows/types.ts
CHANGED
|
@@ -53,9 +53,7 @@ export type WorkflowEffectRecovery = "idempotent" | "manual";
|
|
|
53
53
|
export type WorkflowManagedEffect = {
|
|
54
54
|
/** Stable external effect category, for example `github.comment`. */
|
|
55
55
|
type: string;
|
|
56
|
-
/**
|
|
57
|
-
idempotencyKey: string | ((context: WorkflowNodeContext) => MaybePromise<string>);
|
|
58
|
-
/** Canonical request data used to reject key reuse with another operation. */
|
|
56
|
+
/** Canonical request data used to reject engine-owned key reuse with another operation. */
|
|
59
57
|
request: unknown | ((context: WorkflowNodeContext) => MaybePromise<unknown>);
|
|
60
58
|
/** `manual` never retries after an uncertain child exit. */
|
|
61
59
|
recovery: WorkflowEffectRecovery;
|
|
@@ -97,9 +95,9 @@ export type WorkflowProgressData = {
|
|
|
97
95
|
|
|
98
96
|
export type WorkflowNodeCommon = {
|
|
99
97
|
/**
|
|
100
|
-
* Per-node timeout or a callback that derives it from the run context.
|
|
101
|
-
*
|
|
102
|
-
* default (15 minutes).
|
|
98
|
+
* Per-node active-execution timeout or a callback that derives it from the run context.
|
|
99
|
+
* Waiting, paused, disconnected, and host-down origin-session time does not count.
|
|
100
|
+
* Null disables the deadline. Omission falls back to the engine default (15 minutes).
|
|
103
101
|
*/
|
|
104
102
|
timeoutMs?: number | null | ((context: WorkflowNodeContext) => MaybePromise<number | null>);
|
|
105
103
|
/** Short human-readable label shown in the viewer while the node runs. */
|
|
@@ -436,7 +434,7 @@ export type HumanDecisionSettlementRecord = {
|
|
|
436
434
|
decisionId: string;
|
|
437
435
|
requestDigest: string;
|
|
438
436
|
channel: string;
|
|
439
|
-
state: "confirmed" | "failed";
|
|
437
|
+
state: "confirmed" | "failed" | "unknown";
|
|
440
438
|
createdAt: string;
|
|
441
439
|
finishedAt: string;
|
|
442
440
|
errorCode?: string;
|
|
@@ -719,7 +717,7 @@ export type WorkflowRunState = {
|
|
|
719
717
|
currentNode?: string;
|
|
720
718
|
currentAttemptId?: string;
|
|
721
719
|
currentNodeStartedAt?: string;
|
|
722
|
-
/** Durable
|
|
720
|
+
/** Durable active-execution deadline for the current attempt. Null disables the deadline. */
|
|
723
721
|
currentNodeDeadlineAt?: string | null;
|
|
724
722
|
currentSettingsScopeId?: string;
|
|
725
723
|
currentSettingsChangeNumber?: number;
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
import type { JsonValue } from "../state/json.js";
|
|
2
|
+
import {
|
|
3
|
+
WORKFLOW_MESSAGE_CONTENT_SCHEMA,
|
|
4
|
+
type WorkflowMessageContent,
|
|
5
|
+
type WorkflowStepReason,
|
|
6
|
+
} from "../state/workflow-messages.js";
|
|
7
|
+
import type { AgentStepContract } from "./types.js";
|
|
8
|
+
|
|
9
|
+
export const WORKFLOW_STEP_MESSAGE_TYPE = "pi-workflows-step";
|
|
10
|
+
export const WORKFLOW_DECISION_MESSAGE_TYPE = "pi-workflows-interaction";
|
|
11
|
+
export const WORKFLOW_NOTIFICATION_MESSAGE_TYPE = "pi-workflows-notification";
|
|
12
|
+
export const WORKFLOW_TERMINAL_MESSAGE_TYPE = "pi-workflows-presentation";
|
|
13
|
+
export const WORKFLOW_FOLLOW_UP_MESSAGE_TYPE = "pi-workflows-follow-up";
|
|
14
|
+
|
|
15
|
+
export function stepWorkflowMessageContent(options: {
|
|
16
|
+
workflowMessageId: string;
|
|
17
|
+
requestId: string;
|
|
18
|
+
contract: JsonValue;
|
|
19
|
+
reason: WorkflowStepReason;
|
|
20
|
+
}): WorkflowMessageContent {
|
|
21
|
+
const outer = requireRecord(options.contract, "Stored workflow step contract");
|
|
22
|
+
const agent = requireAgentContract(outer.contract);
|
|
23
|
+
const details: Record<string, JsonValue> = {
|
|
24
|
+
schema: "pi-workflows.agent-step-message.v1",
|
|
25
|
+
kind: "step",
|
|
26
|
+
contract: agent as unknown as JsonValue,
|
|
27
|
+
requestId: options.requestId,
|
|
28
|
+
workflowMessageId: options.workflowMessageId,
|
|
29
|
+
reason: options.reason,
|
|
30
|
+
};
|
|
31
|
+
if (isRecord(outer.presentation)) details.presentation = outer.presentation as JsonValue;
|
|
32
|
+
return {
|
|
33
|
+
schema: WORKFLOW_MESSAGE_CONTENT_SCHEMA,
|
|
34
|
+
customType: WORKFLOW_STEP_MESSAGE_TYPE,
|
|
35
|
+
content: typeof outer.prompt === "string" ? outer.prompt : "Continue the workflow step.",
|
|
36
|
+
display: true,
|
|
37
|
+
details,
|
|
38
|
+
triggerTurn: true,
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export function decisionWorkflowMessageContent(options: {
|
|
43
|
+
workflowMessageId: string;
|
|
44
|
+
requestId: string;
|
|
45
|
+
runId: string;
|
|
46
|
+
contract: JsonValue;
|
|
47
|
+
}): WorkflowMessageContent {
|
|
48
|
+
const contract = requireRecord(options.contract, "Stored workflow decision contract");
|
|
49
|
+
return {
|
|
50
|
+
schema: WORKFLOW_MESSAGE_CONTENT_SCHEMA,
|
|
51
|
+
customType: WORKFLOW_DECISION_MESSAGE_TYPE,
|
|
52
|
+
content: decisionPrompt(contract),
|
|
53
|
+
display: true,
|
|
54
|
+
details: {
|
|
55
|
+
workflowMessageId: options.workflowMessageId,
|
|
56
|
+
requestId: options.requestId,
|
|
57
|
+
runId: options.runId,
|
|
58
|
+
kind: "decision",
|
|
59
|
+
},
|
|
60
|
+
triggerTurn: false,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export function notificationWorkflowMessageContent(options: {
|
|
65
|
+
workflowMessageId: string;
|
|
66
|
+
notificationId: string;
|
|
67
|
+
runId: string;
|
|
68
|
+
kind: "progress" | "final";
|
|
69
|
+
content: string;
|
|
70
|
+
}): WorkflowMessageContent {
|
|
71
|
+
return {
|
|
72
|
+
schema: WORKFLOW_MESSAGE_CONTENT_SCHEMA,
|
|
73
|
+
customType: WORKFLOW_NOTIFICATION_MESSAGE_TYPE,
|
|
74
|
+
content: options.content,
|
|
75
|
+
display: true,
|
|
76
|
+
details: {
|
|
77
|
+
workflowMessageId: options.workflowMessageId,
|
|
78
|
+
notificationId: options.notificationId,
|
|
79
|
+
runId: options.runId,
|
|
80
|
+
kind: options.kind,
|
|
81
|
+
},
|
|
82
|
+
triggerTurn: false,
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export function terminalWorkflowMessageContent(options: {
|
|
87
|
+
workflowMessageId: string;
|
|
88
|
+
runId: string;
|
|
89
|
+
content: string;
|
|
90
|
+
details: JsonValue;
|
|
91
|
+
}): WorkflowMessageContent {
|
|
92
|
+
return {
|
|
93
|
+
schema: WORKFLOW_MESSAGE_CONTENT_SCHEMA,
|
|
94
|
+
customType: WORKFLOW_TERMINAL_MESSAGE_TYPE,
|
|
95
|
+
content: options.content,
|
|
96
|
+
display: false,
|
|
97
|
+
details: {
|
|
98
|
+
workflowMessageId: options.workflowMessageId,
|
|
99
|
+
runId: options.runId,
|
|
100
|
+
kind: "terminal",
|
|
101
|
+
terminal: options.details,
|
|
102
|
+
},
|
|
103
|
+
triggerTurn: true,
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export function followUpWorkflowMessageContent(options: {
|
|
108
|
+
workflowMessageId: string;
|
|
109
|
+
followUpId: string;
|
|
110
|
+
runId: string;
|
|
111
|
+
prompt: string;
|
|
112
|
+
}): WorkflowMessageContent {
|
|
113
|
+
return {
|
|
114
|
+
schema: WORKFLOW_MESSAGE_CONTENT_SCHEMA,
|
|
115
|
+
customType: WORKFLOW_FOLLOW_UP_MESSAGE_TYPE,
|
|
116
|
+
content: options.prompt,
|
|
117
|
+
display: true,
|
|
118
|
+
details: {
|
|
119
|
+
workflowMessageId: options.workflowMessageId,
|
|
120
|
+
followUpId: options.followUpId,
|
|
121
|
+
runId: options.runId,
|
|
122
|
+
kind: "followUp",
|
|
123
|
+
},
|
|
124
|
+
triggerTurn: true,
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function requireAgentContract(value: unknown): AgentStepContract {
|
|
129
|
+
if (
|
|
130
|
+
!isRecord(value) ||
|
|
131
|
+
typeof value.runId !== "string" ||
|
|
132
|
+
typeof value.workflowName !== "string" ||
|
|
133
|
+
typeof value.nodeId !== "string" ||
|
|
134
|
+
typeof value.attemptId !== "string" ||
|
|
135
|
+
(value.completion !== "submit" && value.completion !== "assistant")
|
|
136
|
+
) {
|
|
137
|
+
throw new Error("Stored workflow agent contract is invalid");
|
|
138
|
+
}
|
|
139
|
+
return value as unknown as AgentStepContract;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
function decisionPrompt(contract: Record<string, unknown>): string {
|
|
143
|
+
const title = typeof contract.title === "string" ? contract.title : "Workflow decision";
|
|
144
|
+
const presentation = isRecord(contract.presentation) ? contract.presentation : {};
|
|
145
|
+
const blocks = Array.isArray(presentation.blocks)
|
|
146
|
+
? presentation.blocks.flatMap((block) => decisionBlockText(block))
|
|
147
|
+
: [];
|
|
148
|
+
const choices = isRecord(contract.choices)
|
|
149
|
+
? Object.entries(contract.choices).map(([key, value]) => {
|
|
150
|
+
const choice = isRecord(value) ? value : {};
|
|
151
|
+
const label = typeof choice.label === "string" ? choice.label : key;
|
|
152
|
+
const input = isRecord(choice.input) ? choice.input : undefined;
|
|
153
|
+
const prompt = input === undefined ? "" : `; input: ${String(input.prompt ?? "text")}`;
|
|
154
|
+
return `- ${key}: ${label}${prompt}`;
|
|
155
|
+
})
|
|
156
|
+
: [];
|
|
157
|
+
return [
|
|
158
|
+
title,
|
|
159
|
+
typeof presentation.summary === "string" ? presentation.summary : "",
|
|
160
|
+
...blocks,
|
|
161
|
+
choices.length === 0 ? "" : `Choices:\n${choices.join("\n")}`,
|
|
162
|
+
"A human must answer this protected decision with `/workflow answer`.",
|
|
163
|
+
]
|
|
164
|
+
.filter(Boolean)
|
|
165
|
+
.join("\n\n");
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
function decisionBlockText(value: unknown): string[] {
|
|
169
|
+
if (!isRecord(value)) return [];
|
|
170
|
+
if (value.kind === "paragraph" && typeof value.text === "string") return [value.text];
|
|
171
|
+
if (value.kind === "section" && typeof value.title === "string") return [value.title];
|
|
172
|
+
if (value.kind === "preformatted" && typeof value.text === "string") return [value.text];
|
|
173
|
+
if (value.kind === "bullets" && Array.isArray(value.items)) {
|
|
174
|
+
return [value.items.map((item) => `- ${String(item)}`).join("\n")];
|
|
175
|
+
}
|
|
176
|
+
if (value.kind === "fields" && Array.isArray(value.items)) {
|
|
177
|
+
return [
|
|
178
|
+
value.items
|
|
179
|
+
.flatMap((item) =>
|
|
180
|
+
isRecord(item) && typeof item.label === "string" && typeof item.value === "string"
|
|
181
|
+
? [`${item.label}: ${item.value}`]
|
|
182
|
+
: [],
|
|
183
|
+
)
|
|
184
|
+
.join("\n"),
|
|
185
|
+
];
|
|
186
|
+
}
|
|
187
|
+
return [];
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
function requireRecord(value: unknown, label: string): Record<string, unknown> {
|
|
191
|
+
if (!isRecord(value)) throw new Error(`${label} is invalid`);
|
|
192
|
+
return value;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
196
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
197
|
+
}
|
|
@@ -1,134 +0,0 @@
|
|
|
1
|
-
import type { ExtensionContext } from "@earendil-works/pi-coding-agent";
|
|
2
|
-
import { HumanDecisionStore } from "../workflows/human-decision.js";
|
|
3
|
-
import type { ResolvedHumanDecision, HumanDecisionAnswerSource, HumanDecisionCancellationRecord, HumanDecisionChannelRequest, HumanDecisionResponse } from "../workflows/types.js";
|
|
4
|
-
export type HumanDecisionChannelAnswer = {
|
|
5
|
-
request: HumanDecisionChannelRequest;
|
|
6
|
-
response: HumanDecisionResponse;
|
|
7
|
-
source: HumanDecisionAnswerSource;
|
|
8
|
-
idempotencyKey: string;
|
|
9
|
-
};
|
|
10
|
-
export type HumanDecisionDeliveryResult = {
|
|
11
|
-
status: "confirmed" | "failed" | "unknown";
|
|
12
|
-
channel: string;
|
|
13
|
-
attemptId: string;
|
|
14
|
-
errorCode?: string;
|
|
15
|
-
};
|
|
16
|
-
export type SettledHumanDecision = ResolvedHumanDecision | HumanDecisionCancellationRecord;
|
|
17
|
-
export interface HumanDecisionChannel {
|
|
18
|
-
readonly id: string;
|
|
19
|
-
start(): Promise<void>;
|
|
20
|
-
deliver(request: HumanDecisionChannelRequest): Promise<HumanDecisionDeliveryResult>;
|
|
21
|
-
settle(decision: SettledHumanDecision): Promise<void>;
|
|
22
|
-
stop(): Promise<void>;
|
|
23
|
-
}
|
|
24
|
-
export type DecisionChannelConfig = {
|
|
25
|
-
schema: "pi-workflows.channels.v1";
|
|
26
|
-
audiences: Record<string, {
|
|
27
|
-
channels: string[];
|
|
28
|
-
accept: "first-valid-answer";
|
|
29
|
-
}>;
|
|
30
|
-
telegramProfiles?: Record<string, {
|
|
31
|
-
credential: string;
|
|
32
|
-
allowedUserIds: string[];
|
|
33
|
-
allowedChatIds: string[];
|
|
34
|
-
}>;
|
|
35
|
-
};
|
|
36
|
-
export type DecisionCredentialConfig = {
|
|
37
|
-
schema: "pi-workflows.credentials.v1";
|
|
38
|
-
telegram: Record<string, {
|
|
39
|
-
tokenFile: string;
|
|
40
|
-
}>;
|
|
41
|
-
};
|
|
42
|
-
type ResolvedDecisionCredentials = Record<string, string>;
|
|
43
|
-
export type LoadedDecisionChannelConfig = {
|
|
44
|
-
channels: DecisionChannelConfig;
|
|
45
|
-
credentials: ResolvedDecisionCredentials;
|
|
46
|
-
configDir: string;
|
|
47
|
-
};
|
|
48
|
-
export type TelegramFetch = (input: string, init?: RequestInit) => Promise<{
|
|
49
|
-
ok: boolean;
|
|
50
|
-
status: number;
|
|
51
|
-
json(): Promise<unknown>;
|
|
52
|
-
}>;
|
|
53
|
-
export type PiDecisionUi = Pick<ExtensionContext["ui"], "custom" | "input">;
|
|
54
|
-
export declare function decisionConfigDir(env?: NodeJS.ProcessEnv): string;
|
|
55
|
-
export declare function loadDecisionChannelConfig(configDir?: string): Promise<LoadedDecisionChannelConfig | null>;
|
|
56
|
-
export declare function audienceChannels(config: DecisionChannelConfig | null, audience: string): string[];
|
|
57
|
-
export declare class PiDecisionChannel implements HumanDecisionChannel {
|
|
58
|
-
private readonly options;
|
|
59
|
-
readonly id = "pi";
|
|
60
|
-
private promptAbort;
|
|
61
|
-
private settlementTask;
|
|
62
|
-
constructor(options: {
|
|
63
|
-
actorId: string;
|
|
64
|
-
ui: PiDecisionUi;
|
|
65
|
-
store: HumanDecisionStore;
|
|
66
|
-
onAnswer: (answer: HumanDecisionChannelAnswer) => Promise<void>;
|
|
67
|
-
});
|
|
68
|
-
start(): Promise<void>;
|
|
69
|
-
stop(): Promise<void>;
|
|
70
|
-
deliver(request: HumanDecisionChannelRequest): Promise<HumanDecisionDeliveryResult>;
|
|
71
|
-
private alreadyDecided;
|
|
72
|
-
settle(decision: SettledHumanDecision): Promise<void>;
|
|
73
|
-
private settleOnce;
|
|
74
|
-
}
|
|
75
|
-
export declare class TelegramDecisionChannel implements HumanDecisionChannel {
|
|
76
|
-
readonly id: string;
|
|
77
|
-
private readonly profile;
|
|
78
|
-
private readonly store;
|
|
79
|
-
private readonly fetchFn;
|
|
80
|
-
private readonly apiBase;
|
|
81
|
-
private readonly onAnswer;
|
|
82
|
-
private readonly projection;
|
|
83
|
-
private running;
|
|
84
|
-
private pollAbort;
|
|
85
|
-
private pollTask;
|
|
86
|
-
private readonly settlementTasks;
|
|
87
|
-
constructor(options: {
|
|
88
|
-
profileName: string;
|
|
89
|
-
token: string;
|
|
90
|
-
allowedUserIds: string[];
|
|
91
|
-
allowedChatIds: string[];
|
|
92
|
-
store: HumanDecisionStore;
|
|
93
|
-
configDir?: string;
|
|
94
|
-
onAnswer: (answer: HumanDecisionChannelAnswer) => Promise<void>;
|
|
95
|
-
fetchFn?: TelegramFetch;
|
|
96
|
-
apiBase?: string;
|
|
97
|
-
ownerId?: string;
|
|
98
|
-
});
|
|
99
|
-
start(): Promise<void>;
|
|
100
|
-
stop(): Promise<void>;
|
|
101
|
-
deliver(request: HumanDecisionChannelRequest): Promise<HumanDecisionDeliveryResult>;
|
|
102
|
-
settle(decision: SettledHumanDecision): Promise<void>;
|
|
103
|
-
private settleOnce;
|
|
104
|
-
handleUpdate(value: unknown): Promise<void>;
|
|
105
|
-
private registerCallbacks;
|
|
106
|
-
private channelPath;
|
|
107
|
-
private allowed;
|
|
108
|
-
private isStale;
|
|
109
|
-
private poll;
|
|
110
|
-
private deliverPendingRequests;
|
|
111
|
-
private call;
|
|
112
|
-
}
|
|
113
|
-
export declare function createTelegramChannels(options: {
|
|
114
|
-
config: DecisionChannelConfig;
|
|
115
|
-
credentials: ResolvedDecisionCredentials;
|
|
116
|
-
store: HumanDecisionStore;
|
|
117
|
-
configDir?: string;
|
|
118
|
-
onAnswer: (answer: HumanDecisionChannelAnswer) => Promise<void>;
|
|
119
|
-
fetchFn?: TelegramFetch;
|
|
120
|
-
apiBase?: string;
|
|
121
|
-
}): Map<string, TelegramDecisionChannel>;
|
|
122
|
-
export declare function verifyTelegramTokenFile(tokenFile: string, fetchFn?: TelegramFetch, apiBase?: string): Promise<void>;
|
|
123
|
-
export declare function writeDecisionChannelProfile(options: {
|
|
124
|
-
configDir?: string;
|
|
125
|
-
audience: string;
|
|
126
|
-
profile: string;
|
|
127
|
-
credential: string;
|
|
128
|
-
tokenFile: string;
|
|
129
|
-
allowedUserIds: string[];
|
|
130
|
-
allowedChatIds: string[];
|
|
131
|
-
}): Promise<void>;
|
|
132
|
-
export declare function renderDecisionText(request: HumanDecisionChannelRequest): string;
|
|
133
|
-
export declare function renderTelegramParts(request: HumanDecisionChannelRequest, textLimit?: number): string[];
|
|
134
|
-
export {};
|