@llblab/pi-kit 0.37.1 → 0.38.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 (124) hide show
  1. package/CHANGELOG.md +5 -0
  2. package/README.md +2 -2
  3. package/node_modules/@llblab/pi-state-flow/AGENTS.md +7 -3
  4. package/node_modules/@llblab/pi-state-flow/BACKLOG.md +679 -2
  5. package/node_modules/@llblab/pi-state-flow/CHANGELOG.md +17 -0
  6. package/node_modules/@llblab/pi-state-flow/README.md +30 -14
  7. package/node_modules/@llblab/pi-state-flow/api/modules.ts +11 -0
  8. package/node_modules/@llblab/pi-state-flow/dist/api/modules.d.ts +3 -0
  9. package/node_modules/@llblab/pi-state-flow/dist/api/modules.js +3 -0
  10. package/node_modules/@llblab/pi-state-flow/dist/lib/acquisition.d.ts +7 -4
  11. package/node_modules/@llblab/pi-state-flow/dist/lib/acquisition.js +77 -36
  12. package/node_modules/@llblab/pi-state-flow/dist/lib/artifact.d.ts +2 -0
  13. package/node_modules/@llblab/pi-state-flow/dist/lib/artifact.js +26 -27
  14. package/node_modules/@llblab/pi-state-flow/dist/lib/config.d.ts +3 -0
  15. package/node_modules/@llblab/pi-state-flow/dist/lib/config.js +13 -1
  16. package/node_modules/@llblab/pi-state-flow/dist/lib/context.d.ts +27 -21
  17. package/node_modules/@llblab/pi-state-flow/dist/lib/context.js +144 -46
  18. package/node_modules/@llblab/pi-state-flow/dist/lib/continuation.js +14 -18
  19. package/node_modules/@llblab/pi-state-flow/dist/lib/durable.d.ts +6 -0
  20. package/node_modules/@llblab/pi-state-flow/dist/lib/durable.js +60 -50
  21. package/node_modules/@llblab/pi-state-flow/dist/lib/extension.js +1049 -310
  22. package/node_modules/@llblab/pi-state-flow/dist/lib/history.d.ts +4 -4
  23. package/node_modules/@llblab/pi-state-flow/dist/lib/history.js +15 -3
  24. package/node_modules/@llblab/pi-state-flow/dist/lib/json.d.ts +2 -0
  25. package/node_modules/@llblab/pi-state-flow/dist/lib/json.js +2 -1
  26. package/node_modules/@llblab/pi-state-flow/dist/lib/memory.d.ts +3 -1
  27. package/node_modules/@llblab/pi-state-flow/dist/lib/memory.js +7 -7
  28. package/node_modules/@llblab/pi-state-flow/dist/lib/migration.d.ts +29 -0
  29. package/node_modules/@llblab/pi-state-flow/dist/lib/migration.js +186 -0
  30. package/node_modules/@llblab/pi-state-flow/dist/lib/model-interface.d.ts +17 -0
  31. package/node_modules/@llblab/pi-state-flow/dist/lib/model-interface.js +158 -0
  32. package/node_modules/@llblab/pi-state-flow/dist/lib/module-registry.d.ts +21 -0
  33. package/node_modules/@llblab/pi-state-flow/dist/lib/module-registry.js +108 -0
  34. package/node_modules/@llblab/pi-state-flow/dist/lib/operation.js +3 -2
  35. package/node_modules/@llblab/pi-state-flow/dist/lib/ownership.d.ts +4 -4
  36. package/node_modules/@llblab/pi-state-flow/dist/lib/ownership.js +5 -5
  37. package/node_modules/@llblab/pi-state-flow/dist/lib/planes.d.ts +29 -0
  38. package/node_modules/@llblab/pi-state-flow/dist/lib/planes.js +84 -0
  39. package/node_modules/@llblab/pi-state-flow/dist/lib/protocol.d.ts +6 -3
  40. package/node_modules/@llblab/pi-state-flow/dist/lib/protocol.js +33 -16
  41. package/node_modules/@llblab/pi-state-flow/dist/lib/query.d.ts +21 -4
  42. package/node_modules/@llblab/pi-state-flow/dist/lib/query.js +53 -13
  43. package/node_modules/@llblab/pi-state-flow/dist/lib/recovery.js +5 -2
  44. package/node_modules/@llblab/pi-state-flow/dist/lib/rehydration.d.ts +3 -0
  45. package/node_modules/@llblab/pi-state-flow/dist/lib/rehydration.js +10 -1
  46. package/node_modules/@llblab/pi-state-flow/dist/lib/runtime.d.ts +84 -5
  47. package/node_modules/@llblab/pi-state-flow/dist/lib/runtime.js +570 -20
  48. package/node_modules/@llblab/pi-state-flow/dist/lib/selection.d.ts +10 -0
  49. package/node_modules/@llblab/pi-state-flow/dist/lib/selection.js +32 -0
  50. package/node_modules/@llblab/pi-state-flow/dist/lib/semantic-module.d.ts +79 -0
  51. package/node_modules/@llblab/pi-state-flow/dist/lib/semantic-module.js +187 -0
  52. package/node_modules/@llblab/pi-state-flow/dist/lib/session.d.ts +98 -1
  53. package/node_modules/@llblab/pi-state-flow/dist/lib/session.js +398 -3
  54. package/node_modules/@llblab/pi-state-flow/dist/lib/skills.d.ts +7 -2
  55. package/node_modules/@llblab/pi-state-flow/dist/lib/skills.js +55 -3
  56. package/node_modules/@llblab/pi-state-flow/dist/lib/snapshot.d.ts +67 -14
  57. package/node_modules/@llblab/pi-state-flow/dist/lib/snapshot.js +129 -9
  58. package/node_modules/@llblab/pi-state-flow/dist/lib/state.d.ts +26 -14
  59. package/node_modules/@llblab/pi-state-flow/dist/lib/state.js +61 -19
  60. package/node_modules/@llblab/pi-state-flow/dist/lib/status.d.ts +14 -9
  61. package/node_modules/@llblab/pi-state-flow/dist/lib/status.js +59 -22
  62. package/node_modules/@llblab/pi-state-flow/dist/lib/storage.d.ts +111 -10
  63. package/node_modules/@llblab/pi-state-flow/dist/lib/storage.js +728 -11
  64. package/node_modules/@llblab/pi-state-flow/dist/lib/telegram.d.ts +10 -7
  65. package/node_modules/@llblab/pi-state-flow/dist/lib/telegram.js +50 -14
  66. package/node_modules/@llblab/pi-state-flow/dist/lib/temporal.d.ts +40 -4
  67. package/node_modules/@llblab/pi-state-flow/dist/lib/temporal.js +247 -43
  68. package/node_modules/@llblab/pi-state-flow/dist/lib/transition.d.ts +41 -8
  69. package/node_modules/@llblab/pi-state-flow/dist/lib/transition.js +132 -39
  70. package/node_modules/@llblab/pi-state-flow/dist/package.json +6 -1
  71. package/node_modules/@llblab/pi-state-flow/dist/skills/state-flow-guide/SKILL.md +28 -16
  72. package/node_modules/@llblab/pi-state-flow/dist/skills/state-flow-memory/SKILL.md +12 -8
  73. package/node_modules/@llblab/pi-state-flow/docs/README.md +9 -0
  74. package/node_modules/@llblab/pi-state-flow/docs/architecture.md +76 -43
  75. package/node_modules/@llblab/pi-state-flow/docs/compatibility.md +9 -1
  76. package/node_modules/@llblab/pi-state-flow/docs/fork-contract.md +6 -0
  77. package/node_modules/@llblab/pi-state-flow/docs/lazy-state.md +23 -19
  78. package/node_modules/@llblab/pi-state-flow/docs/protocol-composition-decision.md +66 -0
  79. package/node_modules/@llblab/pi-state-flow/docs/public-module-contract.md +73 -0
  80. package/node_modules/@llblab/pi-state-flow/docs/scope-selection-contract.md +814 -0
  81. package/node_modules/@llblab/pi-state-flow/docs/semantic-compatibility-decision.md +212 -0
  82. package/node_modules/@llblab/pi-state-flow/docs/semantic-extensibility-decision.md +75 -0
  83. package/node_modules/@llblab/pi-state-flow/docs/semantic-handoff-contract.md +174 -0
  84. package/node_modules/@llblab/pi-state-flow/docs/semantic-memory-evaluation.md +166 -0
  85. package/node_modules/@llblab/pi-state-flow/docs/semantic-module-contract.md +84 -0
  86. package/node_modules/@llblab/pi-state-flow/docs/single-scope-interface-contract.md +201 -0
  87. package/node_modules/@llblab/pi-state-flow/docs/temporal-acceptance.md +22 -1
  88. package/node_modules/@llblab/pi-state-flow/docs/usage.md +32 -18
  89. package/node_modules/@llblab/pi-state-flow/lib/acquisition.ts +68 -31
  90. package/node_modules/@llblab/pi-state-flow/lib/artifact.ts +21 -22
  91. package/node_modules/@llblab/pi-state-flow/lib/config.ts +14 -1
  92. package/node_modules/@llblab/pi-state-flow/lib/context.ts +142 -46
  93. package/node_modules/@llblab/pi-state-flow/lib/continuation.ts +14 -17
  94. package/node_modules/@llblab/pi-state-flow/lib/durable.ts +53 -44
  95. package/node_modules/@llblab/pi-state-flow/lib/extension.ts +897 -297
  96. package/node_modules/@llblab/pi-state-flow/lib/history.ts +16 -7
  97. package/node_modules/@llblab/pi-state-flow/lib/json.ts +2 -1
  98. package/node_modules/@llblab/pi-state-flow/lib/memory.ts +10 -9
  99. package/node_modules/@llblab/pi-state-flow/lib/migration.ts +189 -0
  100. package/node_modules/@llblab/pi-state-flow/lib/model-interface.ts +136 -0
  101. package/node_modules/@llblab/pi-state-flow/lib/module-registry.ts +119 -0
  102. package/node_modules/@llblab/pi-state-flow/lib/operation.ts +3 -2
  103. package/node_modules/@llblab/pi-state-flow/lib/ownership.ts +6 -6
  104. package/node_modules/@llblab/pi-state-flow/lib/planes.ts +98 -0
  105. package/node_modules/@llblab/pi-state-flow/lib/protocol.ts +37 -16
  106. package/node_modules/@llblab/pi-state-flow/lib/query.ts +59 -18
  107. package/node_modules/@llblab/pi-state-flow/lib/recovery.ts +5 -2
  108. package/node_modules/@llblab/pi-state-flow/lib/rehydration.ts +10 -1
  109. package/node_modules/@llblab/pi-state-flow/lib/runtime.ts +574 -21
  110. package/node_modules/@llblab/pi-state-flow/lib/selection.ts +39 -0
  111. package/node_modules/@llblab/pi-state-flow/lib/semantic-module.ts +239 -0
  112. package/node_modules/@llblab/pi-state-flow/lib/session.ts +387 -3
  113. package/node_modules/@llblab/pi-state-flow/lib/skills.ts +45 -4
  114. package/node_modules/@llblab/pi-state-flow/lib/snapshot.ts +156 -16
  115. package/node_modules/@llblab/pi-state-flow/lib/state.ts +69 -28
  116. package/node_modules/@llblab/pi-state-flow/lib/status.ts +65 -31
  117. package/node_modules/@llblab/pi-state-flow/lib/storage.ts +770 -18
  118. package/node_modules/@llblab/pi-state-flow/lib/telegram.ts +58 -20
  119. package/node_modules/@llblab/pi-state-flow/lib/temporal.ts +267 -50
  120. package/node_modules/@llblab/pi-state-flow/lib/transition.ts +184 -52
  121. package/node_modules/@llblab/pi-state-flow/package.json +6 -1
  122. package/node_modules/@llblab/pi-state-flow/skills/state-flow-guide/SKILL.md +28 -16
  123. package/node_modules/@llblab/pi-state-flow/skills/state-flow-memory/SKILL.md +12 -8
  124. package/package.json +2 -2
@@ -7,6 +7,7 @@ import { conciseDiagnostic, diagnosticText } from "./protocol.ts";
7
7
  import type { StateFlowMode } from "./snapshot.ts";
8
8
  import { formatScopeRevisionVector } from "./status.ts";
9
9
  import type { ScopeRevisions } from "./temporal.ts";
10
+ import { captureScopeSelection, DEFAULT_SCOPE_SELECTION, type ScopeSelection } from "./selection.ts";
10
11
 
11
12
  export const STATE_FLOW_TELEGRAM_ID = "@llblab/pi-state-flow";
12
13
 
@@ -21,11 +22,13 @@ export function stateFlowTelegramSectionSpecifiers(moduleUrl = import.meta.url):
21
22
  export interface StateFlowTelegramSnapshot {
22
23
  /** The current session's selected mode. */
23
24
  mode: StateFlowMode;
25
+ /** Wanted participating owners, not currently available bodies; omitted legacy ports retain all three. */
26
+ scopes?: ScopeSelection;
24
27
  /** Failed Active restoration fences inference without silently selecting an inactive mode. */
25
28
  inferenceBlocked?: boolean;
26
29
  /** Legacy branch step retained for existing adapter ports; current runtime ports also supply owner revisions. */
27
30
  step: number;
28
- revisions?: ScopeRevisions;
31
+ revisions?: Partial<ScopeRevisions>;
29
32
  bootstrap: boolean;
30
33
  startPending: boolean;
31
34
  }
@@ -34,8 +37,8 @@ export type StateFlowTelegramScope = "global" | "cwd" | "session" | "effective";
34
37
 
35
38
  export interface StateFlowTelegramState {
36
39
  artifacts?: Record<string, unknown>;
37
- contract?: Record<string, unknown>;
38
- working?: Record<string, unknown>;
40
+ strategy?: Record<string, unknown>;
41
+ tactics?: Record<string, unknown>;
39
42
  intents?: Record<string, unknown>;
40
43
  response?: string;
41
44
  lazy?: unknown;
@@ -104,7 +107,7 @@ export interface StateFlowTelegramControlResult {
104
107
 
105
108
  export interface StateFlowTelegramInspection {
106
109
  state: StateFlowTelegramState;
107
- revisions: ScopeRevisions;
110
+ revisions: Partial<ScopeRevisions>;
108
111
  /** A selection can revoke a completed observation before the adapter presents it. */
109
112
  signal?: AbortSignal;
110
113
  }
@@ -113,7 +116,7 @@ export interface StateFlowTelegramPort {
113
116
  snapshot(): StateFlowTelegramSnapshot;
114
117
  state(scope: StateFlowTelegramScope): StateFlowTelegramState;
115
118
  /** Optional additive capability; absent legacy ports retain their branch-step presentation. */
116
- revisions?(): ScopeRevisions;
119
+ revisions?(): Partial<ScopeRevisions>;
117
120
  /** Active may need a settled native boundary; inactive modes apply immediately. */
118
121
  canStartNow(): boolean;
119
122
  /** Select the current session's mode through the same lifecycle owners as the terminal commands. */
@@ -150,11 +153,33 @@ function modeReceiptNotice(mode: StateFlowMode, result: StateFlowTelegramControl
150
153
  return result.message;
151
154
  }
152
155
 
153
- /** One radio-style mode row followed directly by read-only scope actions. */
156
+ function telegramScopes(snapshot: StateFlowTelegramSnapshot): ScopeSelection {
157
+ return captureScopeSelection(snapshot.scopes === undefined ? DEFAULT_SCOPE_SELECTION : snapshot.scopes);
158
+ }
159
+
160
+ function availableInspection(scope: StateFlowTelegramScope, scopes: ScopeSelection): boolean {
161
+ return scope === "effective" ? scopes.length > 1 : scopes.includes(scope);
162
+ }
163
+
164
+ const STATE_FLOW_SCOPE_DESCRIPTIONS = {
165
+ global: "memory shared across projects and sessions.",
166
+ cwd: "memory shared by sessions in this directory.",
167
+ session: "private memory for this session, kept on resume.",
168
+ };
169
+
170
+ /** One radio-style mode row followed by the current participating owners' read-only actions. */
154
171
  export function buildStateFlowSectionView(
155
172
  snapshot: StateFlowTelegramSnapshot,
156
173
  callbackData: (action: string, payload?: string) => string,
157
174
  ): StateFlowTelegramView {
175
+ const scopes = telegramScopes(snapshot);
176
+ const inspected: StateFlowTelegramScope[] = [...scopes, ...(scopes.length > 1 ? ["effective" as const] : [])];
177
+ const inspectionRows: StateFlowTelegramButton[][] = [];
178
+ for (const [index, scope] of inspected.entries()) {
179
+ if (index % 2 === 0) inspectionRows.push([]);
180
+ inspectionRows.at(-1)!.push({ text: STATE_FLOW_SCOPE_LABELS[scope], callback_data: callbackData("inspect", scope) });
181
+ }
182
+ const named = scopes.map(scope => `<code>${scope}</code>`).join(" → ");
158
183
  const modes: StateFlowTelegramButton[] = STATE_FLOW_MODES.map((mode) => ({
159
184
  text: `${mode === snapshot.mode ? STATE_FLOW_SELECTED_MARKERS[mode] : "⚫️"} ${STATE_FLOW_MODE_LABELS[mode]}`,
160
185
  callback_data: callbackData(mode),
@@ -170,22 +195,23 @@ export function buildStateFlowSectionView(
170
195
  "<b>Mode</b> — choose a workflow (switching modes never erases stored memory):",
171
196
  "",
172
197
  "<code>-</code> <code>off</code> (default): regular chat without State Flow memory tools or context.",
173
- "<code>-</code> <code>passive</code>: regular chat with memory tools; available combined memory enters the agent's context.",
198
+ `<code>-</code> <code>passive</code>: regular chat with memory tools; available memory from the selected ${scopes.length === 1 ? "scope" : "scopes"} enters the agent's context.`,
174
199
  "<code>-</code> <code>active</code>: same memory access; each completed answer closes a cycle, and the next request starts from saved state, not the full chat.",
175
200
  "",
176
- "<b>Inspect memory</b> — view stored state even in Off:",
201
+ `<b>Participating scopes:</b> ${named}`,
202
+ ...(!scopes.includes("session") ? ["New answers are delivered, not stored: Session is excluded."] : []),
203
+ "",
204
+ "<b>Inspect participating memory</b> — view available stored state even in Off:",
177
205
  "",
178
- "<code>-</code> <code>global</code>: memory shared across projects and sessions.",
179
- "<code>-</code> <code>cwd</code>: memory shared by sessions in this directory.",
180
- "<code>-</code> <code>session</code>: private memory for this session, kept on resume.",
181
- "<code>-</code> <code>effective</code>: merged Global, CWD and Session state; the agent can use it when memory is enabled and available.",
206
+ ...scopes.map(scope => `<code>-</code> <code>${scope}</code>: ${STATE_FLOW_SCOPE_DESCRIPTIONS[scope]}`),
207
+ ...(scopes.length > 1
208
+ ? [`<code>-</code> <code>effective</code>: validated available ${named} overlay; excluded scopes do not contribute.`]
209
+ : ["This single scope is also the agent's effective state; no separate overlay is needed."]),
182
210
  ].join("\n"),
183
211
  parseMode: "html",
184
212
  replyMarkup: { inline_keyboard: [
185
213
  modes,
186
- ...([["global", "cwd"], ["session", "effective"]] as const).map((row) => row.map((scope) => ({
187
- text: STATE_FLOW_SCOPE_LABELS[scope], callback_data: callbackData("inspect", scope),
188
- }))),
214
+ ...inspectionRows,
189
215
  ] },
190
216
  };
191
217
  }
@@ -224,12 +250,12 @@ function renderStateFlowTelegramField(value: unknown): StateFlowTelegramRichBloc
224
250
  ];
225
251
  }
226
252
 
227
- export function renderStateFlowRichState(scope: StateFlowTelegramScope, revisions: ScopeRevisions, state: StateFlowTelegramState): StateFlowTelegramRichMessage {
253
+ export function renderStateFlowRichState(scope: StateFlowTelegramScope, revisions: Partial<ScopeRevisions>, state: StateFlowTelegramState): StateFlowTelegramRichMessage {
228
254
  const fields: Array<keyof StateFlowTelegramState> = scope === "global" || scope === "cwd"
229
- ? ["intents", "contract", "working", "artifacts", "lazy"]
230
- : ["intents", "contract", "working", "artifacts", "response", "lazy"];
255
+ ? ["intents", "strategy", "tactics", "artifacts", "lazy"]
256
+ : ["intents", "strategy", "tactics", "artifacts", "response", "lazy"];
231
257
  const revision = scope === "effective"
232
- ? formatScopeRevisionVector(revisions)
258
+ ? formatScopeRevisionVector(revisions, captureScopeSelection(Object.keys(revisions)))
233
259
  : `#${revisions[scope]}`;
234
260
  return {
235
261
  blocks: [
@@ -270,10 +296,18 @@ function buildStateFlowTelegramSection(port: StateFlowTelegramPort | StateFlowTe
270
296
  try {
271
297
  if (ctx.action === "inspect") {
272
298
  if (!isStateFlowTelegramScope(ctx.payload)) throw new Error("Unknown State Flow scope");
299
+ const scopes = telegramScopes(port.snapshot());
300
+ if (!availableInspection(ctx.payload, scopes)) throw new Error(ctx.payload === "effective"
301
+ ? "Effective requires at least two participating scopes; inspect the single owner instead"
302
+ : `State Flow ${ctx.payload} scope is excluded from this menu`);
303
+ const checkSelection = () => {
304
+ if (telegramScopes(port.snapshot()).join(" ") !== scopes.join(" ")) throw new Error("State Flow inspection selection changed; select the scope again");
305
+ };
273
306
  let observation: StateFlowTelegramInspection;
274
307
  if ("inspect" in port) {
275
308
  await ctx.answerCallback("Reading State Flow memory");
276
309
  acknowledged = true;
310
+ checkSelection();
277
311
  observation = await port.inspect(ctx.payload);
278
312
  } else {
279
313
  const state = port.state(ctx.payload);
@@ -281,8 +315,12 @@ function buildStateFlowTelegramSection(port: StateFlowTelegramPort | StateFlowTe
281
315
  observation = { state, revisions: port.revisions?.() ?? live.revisions ?? { global: live.step, cwd: live.step, session: live.step } };
282
316
  }
283
317
  observation.signal?.throwIfAborted();
318
+ checkSelection();
284
319
  if (request !== interaction || !isActive()) return "handled" as const;
285
- await ctx.openRich(renderStateFlowRichState(ctx.payload, observation.revisions, observation.state));
320
+ const revisions = ctx.payload === "effective"
321
+ ? Object.fromEntries(scopes.filter(scope => Object.hasOwn(observation.revisions, scope)).map(scope => [scope, observation.revisions[scope]]))
322
+ : observation.revisions;
323
+ await ctx.openRich(renderStateFlowRichState(ctx.payload, revisions, observation.state));
286
324
  if (!acknowledged) await ctx.answerCallback();
287
325
  return "handled" as const;
288
326
  }