@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.
Files changed (86) hide show
  1. package/AGENTS.md +1 -0
  2. package/CHANGELOG.md +10 -0
  3. package/README.md +2 -2
  4. package/node_modules/@llblab/pi-actors/AGENTS.md +5 -3
  5. package/node_modules/@llblab/pi-actors/BACKLOG.md +1 -1
  6. package/node_modules/@llblab/pi-actors/CHANGELOG.md +15 -0
  7. package/node_modules/@llblab/pi-actors/README.md +5 -3
  8. package/node_modules/@llblab/pi-actors/dist/index.js +4 -1
  9. package/node_modules/@llblab/pi-actors/dist/lib/async-runs.d.ts +2 -2
  10. package/node_modules/@llblab/pi-actors/dist/lib/async-runs.js +42 -19
  11. package/node_modules/@llblab/pi-actors/dist/lib/extension-runtime.d.ts +2 -1
  12. package/node_modules/@llblab/pi-actors/dist/lib/extension-runtime.js +7 -2
  13. package/node_modules/@llblab/pi-actors/dist/lib/limits.d.ts +9 -0
  14. package/node_modules/@llblab/pi-actors/dist/lib/limits.js +9 -0
  15. package/node_modules/@llblab/pi-actors/dist/lib/observability.d.ts +10 -11
  16. package/node_modules/@llblab/pi-actors/dist/lib/observability.js +81 -56
  17. package/node_modules/@llblab/pi-actors/dist/lib/pi.d.ts +31 -0
  18. package/node_modules/@llblab/pi-actors/dist/lib/pi.js +180 -0
  19. package/node_modules/@llblab/pi-actors/dist/lib/run-delivery.d.ts +115 -0
  20. package/node_modules/@llblab/pi-actors/dist/lib/run-delivery.js +623 -0
  21. package/node_modules/@llblab/pi-actors/dist/lib/run-ui-runtime.d.ts +3 -0
  22. package/node_modules/@llblab/pi-actors/dist/lib/run-ui-runtime.js +341 -13
  23. package/node_modules/@llblab/pi-actors/dist/lib/runs-trace.d.ts +1 -1
  24. package/node_modules/@llblab/pi-actors/dist/lib/runs-trace.js +5 -3
  25. package/node_modules/@llblab/pi-actors/dist/lib/session-evidence.d.ts +16 -0
  26. package/node_modules/@llblab/pi-actors/dist/lib/session-evidence.js +143 -0
  27. package/node_modules/@llblab/pi-actors/dist/lib/temp.js +1 -1
  28. package/node_modules/@llblab/pi-actors/dist/lib/tools-inspect.js +3 -1
  29. package/node_modules/@llblab/pi-actors/dist/scripts/async-runner.mjs +5 -19
  30. package/node_modules/@llblab/pi-actors/dist/skills/actors/SKILL.md +2 -2
  31. package/node_modules/@llblab/pi-actors/dist/skills/actors/references/runs.md +1 -1
  32. package/node_modules/@llblab/pi-actors/dist/skills/swarm/SKILL.md +1 -1
  33. package/node_modules/@llblab/pi-actors/docs/README.md +1 -0
  34. package/node_modules/@llblab/pi-actors/docs/async-runs.md +8 -4
  35. package/node_modules/@llblab/pi-actors/docs/coordinator-delivery.md +207 -0
  36. package/node_modules/@llblab/pi-actors/index.ts +4 -1
  37. package/node_modules/@llblab/pi-actors/lib/async-runs.ts +42 -21
  38. package/node_modules/@llblab/pi-actors/lib/extension-runtime.ts +8 -3
  39. package/node_modules/@llblab/pi-actors/lib/limits.ts +9 -0
  40. package/node_modules/@llblab/pi-actors/lib/observability.ts +97 -78
  41. package/node_modules/@llblab/pi-actors/lib/pi.ts +210 -0
  42. package/node_modules/@llblab/pi-actors/lib/run-delivery.ts +800 -0
  43. package/node_modules/@llblab/pi-actors/lib/run-ui-runtime.ts +370 -18
  44. package/node_modules/@llblab/pi-actors/lib/runs-trace.ts +6 -4
  45. package/node_modules/@llblab/pi-actors/lib/session-evidence.ts +153 -0
  46. package/node_modules/@llblab/pi-actors/lib/temp.ts +1 -1
  47. package/node_modules/@llblab/pi-actors/lib/tools-inspect.ts +4 -1
  48. package/node_modules/@llblab/pi-actors/package.json +3 -3
  49. package/node_modules/@llblab/pi-actors/scripts/async-runner.mjs +5 -19
  50. package/node_modules/@llblab/pi-actors/skills/actors/SKILL.md +2 -2
  51. package/node_modules/@llblab/pi-actors/skills/actors/references/runs.md +1 -1
  52. package/node_modules/@llblab/pi-actors/skills/swarm/SKILL.md +1 -1
  53. package/node_modules/@llblab/pi-telegram/AGENTS.md +4 -4
  54. package/node_modules/@llblab/pi-telegram/CHANGELOG.md +25 -0
  55. package/node_modules/@llblab/pi-telegram/README.md +4 -4
  56. package/node_modules/@llblab/pi-telegram/docs/activity.md +4 -4
  57. package/node_modules/@llblab/pi-telegram/docs/architecture.md +10 -10
  58. package/node_modules/@llblab/pi-telegram/docs/compact-matrix-literal.md +16 -14
  59. package/node_modules/@llblab/pi-telegram/docs/inbound.md +1 -1
  60. package/node_modules/@llblab/pi-telegram/docs/outbound.md +13 -22
  61. package/node_modules/@llblab/pi-telegram/docs/public-api.md +6 -7
  62. package/node_modules/@llblab/pi-telegram/docs/ui-style.md +4 -5
  63. package/node_modules/@llblab/pi-telegram/docs/voice.md +12 -2
  64. package/node_modules/@llblab/pi-telegram/index.ts +0 -1
  65. package/node_modules/@llblab/pi-telegram/lib/activity.ts +10 -5
  66. package/node_modules/@llblab/pi-telegram/lib/bindings.ts +16 -17
  67. package/node_modules/@llblab/pi-telegram/lib/bus-leader.ts +1 -1
  68. package/node_modules/@llblab/pi-telegram/lib/commands.ts +16 -6
  69. package/node_modules/@llblab/pi-telegram/lib/config.ts +25 -25
  70. package/node_modules/@llblab/pi-telegram/lib/media.ts +12 -2
  71. package/node_modules/@llblab/pi-telegram/lib/menu-settings.ts +10 -73
  72. package/node_modules/@llblab/pi-telegram/lib/outbound-buttons.ts +9 -8
  73. package/node_modules/@llblab/pi-telegram/lib/outbound-markup.ts +212 -82
  74. package/node_modules/@llblab/pi-telegram/lib/routing.ts +78 -36
  75. package/node_modules/@llblab/pi-telegram/lib/status.ts +23 -4
  76. package/node_modules/@llblab/pi-telegram/lib/turns.ts +10 -1
  77. package/node_modules/@llblab/pi-telegram/lib/updates.ts +1 -1
  78. package/node_modules/@llblab/pi-telegram/package.json +1 -1
  79. package/node_modules/@llblab/pi-telegram/skills/generated-control-surface/SKILL.md +61 -205
  80. package/node_modules/@llblab/pi-telegram/skills/generated-control-surface/references/capability-adapters.md +27 -0
  81. package/node_modules/@llblab/pi-telegram/skills/generated-control-surface/references/layout-and-state.md +35 -0
  82. package/node_modules/@llblab/pi-telegram/skills/telegram-bridge/SKILL.md +70 -110
  83. package/node_modules/@llblab/pi-telegram/skills/telegram-bridge/references/configuration.md +15 -0
  84. package/node_modules/@llblab/pi-telegram/skills/telegram-bridge/references/delivery-and-threads.md +27 -0
  85. package/node_modules/@llblab/pi-telegram/skills/telegram-bridge/references/diagnosis.md +14 -0
  86. package/package.json +3 -3
@@ -3,6 +3,9 @@
3
3
  * Zones: pi agent sdk boundary, extension host adapters
4
4
  * Owns direct pi SDK imports and exposes narrow pi-actors-facing helpers/types for the composition root.
5
5
  */
6
+ import * as SessionEvidence from "./session-evidence.js";
7
+ export const RUN_COMPLETION_BATCH_CUSTOM_TYPE = "pi-actors-run-batch";
8
+ export const RUN_STEER_CUSTOM_TYPE = "pi-actors-run-steer";
6
9
  export function getSessionId(ctx) {
7
10
  return ctx.sessionManager.getSessionId();
8
11
  }
@@ -15,6 +18,183 @@ export function createNotificationSink(pi, ctx) {
15
18
  }),
16
19
  };
17
20
  }
21
+ export function sendRunCompletionBatch(pi, batchId, content) {
22
+ pi.sendMessage({
23
+ customType: RUN_COMPLETION_BATCH_CUSTOM_TYPE,
24
+ content,
25
+ display: false,
26
+ details: {
27
+ pi_actors_delivery: {
28
+ batch_id: batchId,
29
+ kind: "completion_batch",
30
+ },
31
+ },
32
+ }, {
33
+ deliverAs: "followUp",
34
+ triggerTurn: true,
35
+ });
36
+ }
37
+ export function sendRunSteer(pi, input) {
38
+ pi.sendMessage({
39
+ customType: RUN_STEER_CUSTOM_TYPE,
40
+ content: input.content,
41
+ display: false,
42
+ details: {
43
+ pi_actors_delivery: {
44
+ event_id: input.eventId,
45
+ kind: "urgent_steer",
46
+ steer_id: input.steerId,
47
+ },
48
+ },
49
+ }, {
50
+ deliverAs: "steer",
51
+ triggerTurn: true,
52
+ });
53
+ }
54
+ function completionBatchMessage(message) {
55
+ if (!message || typeof message !== "object" || Array.isArray(message))
56
+ return undefined;
57
+ const record = message;
58
+ if (record.customType !== RUN_COMPLETION_BATCH_CUSTOM_TYPE ||
59
+ typeof record.content !== "string")
60
+ return undefined;
61
+ const details = record.details;
62
+ if (!details || typeof details !== "object" || Array.isArray(details))
63
+ return undefined;
64
+ const delivery = details.pi_actors_delivery;
65
+ if (!delivery || typeof delivery !== "object" || Array.isArray(delivery))
66
+ return undefined;
67
+ const envelope = delivery;
68
+ if (envelope.kind !== "completion_batch" ||
69
+ typeof envelope.batch_id !== "string" ||
70
+ !envelope.batch_id ||
71
+ envelope.batch_id.length > 128)
72
+ return undefined;
73
+ return { batchId: envelope.batch_id, content: record.content };
74
+ }
75
+ /** Collapse exact retry duplicates and remove conflicting delivery envelopes. */
76
+ export function dedupeRunCompletionBatchContext(messages) {
77
+ const batches = new Map();
78
+ const conflicts = new Set();
79
+ for (const message of messages) {
80
+ const batch = completionBatchMessage(message);
81
+ if (!batch)
82
+ continue;
83
+ const existing = batches.get(batch.batchId);
84
+ if (existing !== undefined && existing !== batch.content) {
85
+ conflicts.add(batch.batchId);
86
+ }
87
+ else if (existing === undefined) {
88
+ batches.set(batch.batchId, batch.content);
89
+ }
90
+ }
91
+ const retained = new Set();
92
+ const filtered = messages.filter((message) => {
93
+ const batch = completionBatchMessage(message);
94
+ if (!batch)
95
+ return true;
96
+ if (conflicts.has(batch.batchId) || retained.has(batch.batchId))
97
+ return false;
98
+ retained.add(batch.batchId);
99
+ return true;
100
+ });
101
+ for (const batchId of conflicts)
102
+ batches.delete(batchId);
103
+ return { batches, conflicts, messages: filtered };
104
+ }
105
+ export function removeRunCompletionBatchFromContext(messages, batchId) {
106
+ return messages.filter((message) => completionBatchMessage(message)?.batchId !== batchId);
107
+ }
108
+ function steerMessage(message) {
109
+ if (!message || typeof message !== "object" || Array.isArray(message))
110
+ return undefined;
111
+ const record = message;
112
+ if (record.customType !== RUN_STEER_CUSTOM_TYPE || typeof record.content !== "string") {
113
+ return undefined;
114
+ }
115
+ const details = record.details;
116
+ if (!details || typeof details !== "object" || Array.isArray(details))
117
+ return undefined;
118
+ const delivery = details.pi_actors_delivery;
119
+ if (!delivery || typeof delivery !== "object" || Array.isArray(delivery))
120
+ return undefined;
121
+ const envelope = delivery;
122
+ if (envelope.kind !== "urgent_steer" ||
123
+ typeof envelope.steer_id !== "string" ||
124
+ !envelope.steer_id ||
125
+ envelope.steer_id.length > 128 ||
126
+ typeof envelope.event_id !== "string" ||
127
+ !envelope.event_id ||
128
+ envelope.event_id.length > 256)
129
+ return undefined;
130
+ return {
131
+ content: record.content,
132
+ eventId: envelope.event_id,
133
+ steerId: envelope.steer_id,
134
+ };
135
+ }
136
+ export function dedupeRunSteerContext(messages) {
137
+ const conflicts = new Set();
138
+ const steers = new Map();
139
+ for (const message of messages) {
140
+ const steer = steerMessage(message);
141
+ if (!steer)
142
+ continue;
143
+ const existing = steers.get(steer.steerId);
144
+ if (existing &&
145
+ (existing.content !== steer.content || existing.eventId !== steer.eventId)) {
146
+ conflicts.add(steer.steerId);
147
+ }
148
+ else if (!existing) {
149
+ steers.set(steer.steerId, {
150
+ content: steer.content,
151
+ eventId: steer.eventId,
152
+ });
153
+ }
154
+ }
155
+ const retained = new Set();
156
+ const filtered = messages.filter((message) => {
157
+ const steer = steerMessage(message);
158
+ if (!steer)
159
+ return true;
160
+ if (conflicts.has(steer.steerId) || retained.has(steer.steerId))
161
+ return false;
162
+ retained.add(steer.steerId);
163
+ return true;
164
+ });
165
+ for (const steerId of conflicts)
166
+ steers.delete(steerId);
167
+ return { conflicts, messages: filtered, steers };
168
+ }
169
+ export function removeRunSteerFromContext(messages, steerId) {
170
+ return messages.filter((message) => steerMessage(message)?.steerId !== steerId);
171
+ }
172
+ export function inspectRunSteerSessionEvidence(ctx, input) {
173
+ return SessionEvidence.inspectBoundedActiveSessionEntries({
174
+ getEntry: (id) => ctx.sessionManager.getEntry(id),
175
+ leaf: ctx.sessionManager.getLeafEntry(),
176
+ match: (entry) => {
177
+ const steer = steerMessage(entry);
178
+ if (!steer || steer.steerId !== input.steerId)
179
+ return undefined;
180
+ return steer.content === input.content && steer.eventId === input.eventId
181
+ ? "present"
182
+ : "conflict";
183
+ },
184
+ });
185
+ }
186
+ export function inspectRunCompletionBatchSessionEvidence(ctx, batchId, content) {
187
+ return SessionEvidence.inspectBoundedActiveSessionEntries({
188
+ getEntry: (id) => ctx.sessionManager.getEntry(id),
189
+ leaf: ctx.sessionManager.getLeafEntry(),
190
+ match: (entry) => {
191
+ const batch = completionBatchMessage(entry);
192
+ if (!batch || batch.batchId !== batchId)
193
+ return undefined;
194
+ return batch.content === content ? "present" : "conflict";
195
+ },
196
+ });
197
+ }
18
198
  export function registerToolDefinitions(pi, definitions) {
19
199
  for (const definition of definitions)
20
200
  pi.registerTool(definition);
@@ -0,0 +1,115 @@
1
+ /**
2
+ * Coordinator delivery persistence.
3
+ * Zones: owner-scoped completion batches, delivery phase fencing, bounded receipts
4
+ * Owns durable delivery state; excludes Run discovery, Pi scheduling, and model formatting.
5
+ */
6
+ export type RunCompletionDeliveryStatus = "done" | "failed" | "killed" | "exited";
7
+ export type RunDeliveryPhase = "pending" | "queued" | "presented";
8
+ export interface RunCompletionBatchMember {
9
+ artifacts?: Record<string, string>;
10
+ run: string;
11
+ run_instance_id: string;
12
+ state_dir: string;
13
+ status: RunCompletionDeliveryStatus;
14
+ summary: string;
15
+ terminal_at: string;
16
+ }
17
+ export interface RunCompletionBatch {
18
+ attempts?: number;
19
+ batch_id: string;
20
+ created_at: string;
21
+ last_error?: string;
22
+ last_failed_at?: string;
23
+ members: RunCompletionBatchMember[];
24
+ phase: RunDeliveryPhase;
25
+ presented_at?: string;
26
+ queued_at?: string;
27
+ }
28
+ export interface RunSteerEnvelope {
29
+ attempts?: number;
30
+ content: string;
31
+ created_at: string;
32
+ event_id: string;
33
+ kind: string;
34
+ last_error?: string;
35
+ last_failed_at?: string;
36
+ level: "info" | "warning" | "error";
37
+ occurred_at: string;
38
+ phase: RunDeliveryPhase;
39
+ presented_at?: string;
40
+ queued_at?: string;
41
+ run: string;
42
+ run_instance_id: string;
43
+ state_dir: string;
44
+ steer_id: string;
45
+ }
46
+ export interface RunDeliveryReceipt {
47
+ delivery_id: string;
48
+ kind: "completion_batch" | "urgent_steer";
49
+ presented_at: string;
50
+ }
51
+ export interface RunDeliveryJournal {
52
+ completion_batch?: RunCompletionBatch;
53
+ owner_id: string;
54
+ receipts: RunDeliveryReceipt[];
55
+ schema: "run-delivery-v1";
56
+ steers: RunSteerEnvelope[];
57
+ }
58
+ export interface AdmitRunCompletionBatchInput {
59
+ batchId?: string;
60
+ members: RunCompletionBatchMember[];
61
+ now?: Date;
62
+ ownerId: string;
63
+ tempDir: string;
64
+ }
65
+ export interface RunDeliveryTransitionInput {
66
+ batchId: string;
67
+ now?: Date;
68
+ ownerId: string;
69
+ tempDir: string;
70
+ }
71
+ export interface AdmitRunSteerEnvelopeInput {
72
+ content: string;
73
+ eventId: string;
74
+ kind: string;
75
+ level: "info" | "warning" | "error";
76
+ now?: Date;
77
+ occurredAt: string;
78
+ ownerId: string;
79
+ run: string;
80
+ runInstanceId: string;
81
+ stateDir: string;
82
+ steerId?: string;
83
+ tempDir: string;
84
+ }
85
+ export interface RunSteerTransitionInput {
86
+ now?: Date;
87
+ ownerId: string;
88
+ steerId: string;
89
+ tempDir: string;
90
+ }
91
+ export declare function getRunDeliveryJournalPath(tempDir: string, ownerId: string): string;
92
+ export declare function readRunDeliveryJournal(tempDir: string, ownerId: string): RunDeliveryJournal;
93
+ export declare function admitRunCompletionBatch(input: AdmitRunCompletionBatchInput): RunCompletionBatch;
94
+ export declare function markRunCompletionBatchQueued(input: RunDeliveryTransitionInput): boolean;
95
+ export declare function resetRunCompletionBatchPending(input: Omit<RunDeliveryTransitionInput, "now">): boolean;
96
+ export declare function recordRunCompletionBatchDeliveryFailure(input: RunDeliveryTransitionInput & {
97
+ error: unknown;
98
+ }): boolean;
99
+ export declare function markRunCompletionBatchPresented(input: RunDeliveryTransitionInput): boolean;
100
+ export declare function finalizeRunCompletionBatch(input: Omit<RunDeliveryTransitionInput, "now">): boolean;
101
+ export declare function getRunSteerDeliveryId(input: {
102
+ eventId: string;
103
+ runInstanceId: string;
104
+ stateDir: string;
105
+ }): string;
106
+ export declare function admitRunSteerEnvelope(input: AdmitRunSteerEnvelopeInput): RunSteerEnvelope | undefined;
107
+ export declare function markRunSteerQueued(input: RunSteerTransitionInput): boolean;
108
+ export declare function resetRunSteerPending(input: Omit<RunSteerTransitionInput, "now">): boolean;
109
+ export declare function recordRunSteerDeliveryFailure(input: RunSteerTransitionInput & {
110
+ error: unknown;
111
+ }): boolean;
112
+ export declare function markRunSteerPresented(input: RunSteerTransitionInput): boolean;
113
+ export declare function finalizeRunSteer(input: Omit<RunSteerTransitionInput, "now">): boolean;
114
+ /** Format one immutable batch for a model-bound custom message. */
115
+ export declare function formatRunCompletionBatchMessage(batch: RunCompletionBatch): string;