@hassangameryt/freeflow 0.5.0 → 0.6.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 (284) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/.codex-plugin/plugin.json +1 -1
  4. package/README.md +148 -154
  5. package/capabilities/cognitive-routing/SKILL.md +229 -0
  6. package/capabilities/context-virtualization/SKILL.md +103 -0
  7. package/capabilities/conversation-history/SKILL.md +53 -0
  8. package/command-surface.json +6 -13
  9. package/hooks/freeflow-runtime-context.mjs +35 -91
  10. package/hooks/tests/check-runtime-context-hook.sh +56 -39
  11. package/package.json +24 -16
  12. package/pi-extension/dist/cognitive-routing/commands.js +96 -0
  13. package/pi-extension/dist/cognitive-routing/config.js +236 -0
  14. package/pi-extension/dist/cognitive-routing/controller.js +862 -0
  15. package/pi-extension/dist/cognitive-routing/history.js +439 -0
  16. package/pi-extension/dist/cognitive-routing/host.js +126 -0
  17. package/pi-extension/dist/cognitive-routing/runtime.js +43 -0
  18. package/pi-extension/dist/cognitive-routing/tool.js +211 -0
  19. package/pi-extension/dist/cognitive-routing/types.js +6 -0
  20. package/pi-extension/dist/context-virtualization/commands.js +89 -0
  21. package/pi-extension/dist/context-virtualization/projector.js +42 -0
  22. package/pi-extension/dist/context-virtualization/runtime.js +356 -0
  23. package/pi-extension/dist/context-virtualization/state.js +57 -0
  24. package/pi-extension/dist/context-virtualization/types.js +10 -0
  25. package/pi-extension/dist/conversation-history/passages.js +66 -0
  26. package/pi-extension/dist/conversation-history/ranking.js +105 -0
  27. package/pi-extension/dist/conversation-history/runtime.js +226 -0
  28. package/pi-extension/dist/conversation-history/search.js +56 -0
  29. package/pi-extension/dist/conversation-history/types.js +1 -0
  30. package/pi-extension/dist/freeflow-context/resolver.js +120 -0
  31. package/pi-extension/dist/freeflow-context/runtime.js +80 -0
  32. package/pi-extension/dist/freeflow-context/source-projector.js +95 -0
  33. package/pi-extension/dist/freeflow-context/tool.js +308 -0
  34. package/pi-extension/dist/freeflow-context/types.js +12 -0
  35. package/pi-extension/dist/freeflow-context/visibility.js +28 -0
  36. package/pi-extension/dist/index.js +516 -98
  37. package/pi-extension/dist/runtime/runtime-context.js +318 -271
  38. package/pi-extension/dist/runtime/runtime-identity.js +5 -0
  39. package/pi-extension/dist/settings/settings-tui.js +78 -0
  40. package/pi-extension/dist/settings/settings-ui.js +593 -563
  41. package/pi-extension/dist/ui/text-component.js +57 -0
  42. package/pi-extension/src/cognitive-routing/commands.ts +119 -0
  43. package/pi-extension/src/cognitive-routing/config.ts +307 -0
  44. package/pi-extension/src/cognitive-routing/controller.ts +1118 -0
  45. package/pi-extension/src/cognitive-routing/history.ts +638 -0
  46. package/pi-extension/src/cognitive-routing/host.ts +172 -0
  47. package/pi-extension/src/cognitive-routing/runtime.ts +57 -0
  48. package/pi-extension/src/cognitive-routing/tool.ts +272 -0
  49. package/pi-extension/src/cognitive-routing/types.ts +89 -0
  50. package/pi-extension/src/context-virtualization/commands.ts +111 -0
  51. package/pi-extension/src/context-virtualization/projector.ts +62 -0
  52. package/pi-extension/src/context-virtualization/runtime.ts +406 -0
  53. package/pi-extension/src/context-virtualization/state.ts +79 -0
  54. package/pi-extension/src/context-virtualization/types.ts +92 -0
  55. package/pi-extension/src/conversation-history/passages.ts +81 -0
  56. package/pi-extension/src/conversation-history/ranking.ts +155 -0
  57. package/pi-extension/src/conversation-history/runtime.ts +250 -0
  58. package/pi-extension/src/conversation-history/search.ts +79 -0
  59. package/pi-extension/src/conversation-history/types.ts +31 -0
  60. package/pi-extension/src/freeflow-context/resolver.ts +139 -0
  61. package/pi-extension/src/freeflow-context/runtime.ts +100 -0
  62. package/pi-extension/src/freeflow-context/source-projector.ts +106 -0
  63. package/pi-extension/src/freeflow-context/tool.ts +360 -0
  64. package/pi-extension/src/freeflow-context/types.ts +70 -0
  65. package/pi-extension/src/freeflow-context/visibility.ts +53 -0
  66. package/pi-extension/src/index.ts +553 -101
  67. package/pi-extension/src/runtime/runtime-context.ts +339 -281
  68. package/pi-extension/src/runtime/runtime-identity.ts +8 -0
  69. package/pi-extension/src/settings/settings-tui.ts +93 -0
  70. package/pi-extension/src/settings/settings-ui.ts +700 -613
  71. package/pi-extension/src/ui/text-component.ts +66 -0
  72. package/pi-extension/tests/cognitive-routing/commands.test.js +134 -0
  73. package/pi-extension/tests/cognitive-routing/controller.test.js +1099 -0
  74. package/pi-extension/tests/cognitive-routing/extension-lifecycle.test.js +1071 -0
  75. package/pi-extension/tests/cognitive-routing/history.test.js +274 -0
  76. package/pi-extension/tests/cognitive-routing/host-fixture.js +4 -0
  77. package/pi-extension/tests/cognitive-routing/host-identity.test.js +63 -0
  78. package/pi-extension/tests/cognitive-routing/profile-resolution.test.js +236 -0
  79. package/pi-extension/tests/cognitive-routing/tool.test.js +230 -0
  80. package/pi-extension/tests/context-virtualization/extension.test.js +749 -0
  81. package/pi-extension/tests/context-virtualization/projector.test.js +110 -0
  82. package/pi-extension/tests/context-virtualization/runtime.test.js +216 -0
  83. package/pi-extension/tests/conversation-history/runtime.test.js +98 -0
  84. package/pi-extension/tests/conversation-history/search.test.js +97 -0
  85. package/pi-extension/tests/integration/pi-extension.test.js +927 -2048
  86. package/pi-extension/tests/integration/prompt-architecture.test.js +305 -0
  87. package/runtime/prompts/cognitive-routing.md +9 -0
  88. package/runtime/prompts/context-virtualization.md +3 -0
  89. package/runtime/prompts/conversation-history.md +3 -0
  90. package/runtime/prompts/core.md +13 -0
  91. package/runtime/prompts/interaction-contract.md +7 -0
  92. package/runtime/prompts/skills.md +65 -0
  93. package/skills/action-selection/SKILL.md +91 -0
  94. package/skills/bypass/SKILL.md +3 -2
  95. package/skills/commit-work/SKILL.md +1 -1
  96. package/skills/commit-work/references/staging-decisions.md +1 -1
  97. package/skills/decision-gate/SKILL.md +1 -1
  98. package/skills/design-for-depth/SKILL.md +14 -33
  99. package/skills/design-for-depth/references/design-pressure-signals.md +1 -1
  100. package/skills/design-for-depth/references/interface-design-loop.md +1 -1
  101. package/skills/design-for-depth/references/software-design-philosophy.md +1 -1
  102. package/skills/diagnose-failure/SKILL.md +20 -14
  103. package/skills/diagnose-failure/references/diagnostic-loop-catalog.md +1 -3
  104. package/skills/diagnose-failure/references/{flaky-and-performance.md → flaky-and-performance-diagnosis.md} +1 -1
  105. package/skills/discuss/SKILL.md +34 -22
  106. package/skills/discuss/references/discussion-continuity.md +71 -0
  107. package/skills/evaluate-skill/SKILL.md +5 -5
  108. package/skills/evaluate-skill/references/{definition-schema.md → evaluation-definition-schema.md} +42 -2
  109. package/skills/evaluate-skill/references/execution-and-evidence.md +8 -3
  110. package/skills/evaluate-skill/scripts/lib/definitions.mjs +114 -3
  111. package/skills/evaluate-skill/scripts/lib/grade-interaction.mjs +156 -1
  112. package/skills/evaluate-skill/scripts/lib/grade.mjs +9 -1
  113. package/skills/evaluate-skill/scripts/lib/pi.mjs +147 -32
  114. package/skills/evaluate-skill/scripts/lib/rpc.mjs +4 -4
  115. package/skills/evaluate-skill/scripts/lib/runner.mjs +36 -14
  116. package/skills/evaluate-skill/scripts/lib/sandbox.mjs +92 -0
  117. package/skills/evaluate-skill/scripts/pi-guard.mjs +1 -1
  118. package/skills/evaluate-skill/scripts/pi-observer.mjs +66 -0
  119. package/skills/evaluate-skill/scripts/skill-eval.mjs +6 -5
  120. package/skills/execute-work/SKILL.md +18 -15
  121. package/skills/execute-work/references/code-practices.md +1 -1
  122. package/skills/execute-work/references/execute-work-edges.md +42 -0
  123. package/skills/finish-branch/SKILL.md +2 -2
  124. package/skills/finish-branch/references/integration-options.md +1 -1
  125. package/skills/handoff/SKILL.md +3 -3
  126. package/skills/launch-work/SKILL.md +1 -1
  127. package/skills/launch-work/references/launch-readiness.md +2 -2
  128. package/skills/migration-work/SKILL.md +2 -2
  129. package/skills/migration-work/references/migration-lifecycle.md +1 -1
  130. package/skills/mode-contract/SKILL.md +4 -4
  131. package/skills/release-work/SKILL.md +1 -1
  132. package/skills/release-work/references/release-evidence.md +1 -1
  133. package/skills/review-artifact/SKILL.md +28 -26
  134. package/skills/review-work/SKILL.md +28 -26
  135. package/skills/review-work/references/{reviewer-prompt.md → independent-work-reviewer-contract.md} +1 -1
  136. package/skills/review-work/references/security-risk-lens.md +1 -1
  137. package/skills/setup-freeflow/SKILL.md +3 -1
  138. package/skills/setup-freeflow/references/activation-contract.md +2 -2
  139. package/skills/setup-freeflow/references/host-setup.md +2 -2
  140. package/skills/simplify-code/SKILL.md +1 -1
  141. package/skills/simplify-code/references/simplification-patterns.md +1 -1
  142. package/skills/tdd/SKILL.md +18 -38
  143. package/skills/tdd/references/test-design.md +2 -2
  144. package/skills/track-work/SKILL.md +362 -58
  145. package/skills/track-work/scripts/lib/codec.mjs +570 -0
  146. package/skills/track-work/scripts/lib/commands.mjs +568 -0
  147. package/skills/track-work/scripts/lib/contract.mjs +303 -0
  148. package/skills/track-work/scripts/lib/model.mjs +506 -0
  149. package/skills/track-work/scripts/lib/operations.mjs +965 -0
  150. package/skills/track-work/scripts/lib/record-store.mjs +264 -0
  151. package/skills/track-work/scripts/lib/result.mjs +37 -0
  152. package/skills/track-work/scripts/lib/rewrites.mjs +740 -0
  153. package/skills/track-work/scripts/lib/schema.mjs +277 -0
  154. package/skills/track-work/scripts/lib/source-inventory.mjs +162 -0
  155. package/skills/track-work/scripts/lib/views.mjs +443 -0
  156. package/skills/track-work/scripts/lib/workspace.mjs +134 -0
  157. package/skills/track-work/scripts/working-record.mjs +122 -0
  158. package/skills/verify-work/SKILL.md +14 -2
  159. package/skills/verify-work/references/browser-runtime-evidence.md +1 -1
  160. package/skills/verify-work/references/integration-evidence.md +1 -1
  161. package/skills/verify-work/references/performance-evidence.md +1 -1
  162. package/skills/workflow/SKILL.md +105 -53
  163. package/skills/workflow/references/domain-skill-composition.md +22 -42
  164. package/skills/write-plan/SKILL.md +1 -1
  165. package/skills/write-skill/SKILL.md +3 -2
  166. package/skills/write-skill/references/progressive-disclosure.md +17 -3
  167. package/capabilities/output-router/SKILL.md +0 -206
  168. package/capabilities/output-router/references/safety-policy.md +0 -40
  169. package/capabilities/output-router/references/setup.md +0 -110
  170. package/pi-extension/dist/output-router/host-producer-identification.js +0 -232
  171. package/pi-extension/dist/output-router/native-safety-net.js +0 -216
  172. package/pi-extension/dist/output-router/observed-tool-routing.js +0 -122
  173. package/pi-extension/dist/output-router/renderers.js +0 -1023
  174. package/pi-extension/dist/output-router/router-tools.js +0 -554
  175. package/pi-extension/dist/output-router/schemas.js +0 -383
  176. package/pi-extension/dist/output-router/status.js +0 -744
  177. package/pi-extension/dist/output-router/utils.js +0 -502
  178. package/pi-extension/src/output-router/host-producer-identification.ts +0 -256
  179. package/pi-extension/src/output-router/native-safety-net.ts +0 -248
  180. package/pi-extension/src/output-router/observed-tool-routing.ts +0 -134
  181. package/pi-extension/src/output-router/renderers.ts +0 -1108
  182. package/pi-extension/src/output-router/router-tools.ts +0 -579
  183. package/pi-extension/src/output-router/schemas.ts +0 -387
  184. package/pi-extension/src/output-router/status.ts +0 -791
  185. package/pi-extension/src/output-router/utils.ts +0 -554
  186. package/pi-extension/tests/output-router/observed-producers.test.js +0 -132
  187. package/pi-extension/tests/output-router/search.test.js +0 -722
  188. package/router/dist/benchmarks/benchmark-harness.d.ts +0 -35
  189. package/router/dist/benchmarks/benchmark-harness.js +0 -92
  190. package/router/dist/benchmarks/benchmarks.d.ts +0 -109
  191. package/router/dist/benchmarks/benchmarks.js +0 -979
  192. package/router/dist/benchmarks/codex-qa-benchmarks.d.ts +0 -95
  193. package/router/dist/benchmarks/codex-qa-benchmarks.js +0 -500
  194. package/router/dist/benchmarks/command-benchmarks.d.ts +0 -143
  195. package/router/dist/benchmarks/command-benchmarks.js +0 -698
  196. package/router/dist/benchmarks/context-mode-normalized-benchmarks.d.ts +0 -82
  197. package/router/dist/benchmarks/context-mode-normalized-benchmarks.js +0 -773
  198. package/router/dist/benchmarks/context-mode-real-deep-benchmark.d.ts +0 -132
  199. package/router/dist/benchmarks/context-mode-real-deep-benchmark.js +0 -1380
  200. package/router/dist/benchmarks/context-saving-baseline.d.ts +0 -60
  201. package/router/dist/benchmarks/context-saving-baseline.js +0 -470
  202. package/router/dist/benchmarks/index-benchmarks.d.ts +0 -103
  203. package/router/dist/benchmarks/index-benchmarks.js +0 -862
  204. package/router/dist/benchmarks/storage-policy-benchmarks.d.ts +0 -101
  205. package/router/dist/benchmarks/storage-policy-benchmarks.js +0 -618
  206. package/router/dist/benchmarks/vault-index-benchmarks.d.ts +0 -56
  207. package/router/dist/benchmarks/vault-index-benchmarks.js +0 -322
  208. package/router/dist/config/config.d.ts +0 -103
  209. package/router/dist/config/config.js +0 -632
  210. package/router/dist/config/router-contract.d.ts +0 -10
  211. package/router/dist/config/router-contract.js +0 -54
  212. package/router/dist/config/schema.d.ts +0 -27
  213. package/router/dist/config/schema.js +0 -648
  214. package/router/dist/config/types.d.ts +0 -573
  215. package/router/dist/config/types.js +0 -41
  216. package/router/dist/evidence/bounded-evidence.d.ts +0 -40
  217. package/router/dist/evidence/bounded-evidence.js +0 -323
  218. package/router/dist/evidence/evidence-range-selector.d.ts +0 -24
  219. package/router/dist/evidence/evidence-range-selector.js +0 -232
  220. package/router/dist/evidence/evidence-search.d.ts +0 -27
  221. package/router/dist/evidence/evidence-search.js +0 -490
  222. package/router/dist/evidence/evidence.d.ts +0 -38
  223. package/router/dist/evidence/evidence.js +0 -200
  224. package/router/dist/evidence/failure-contracts.d.ts +0 -37
  225. package/router/dist/evidence/failure-contracts.js +0 -166
  226. package/router/dist/evidence/line-ranges.d.ts +0 -24
  227. package/router/dist/evidence/line-ranges.js +0 -22
  228. package/router/dist/experiments/local-index.d.ts +0 -64
  229. package/router/dist/experiments/local-index.js +0 -581
  230. package/router/dist/index.d.ts +0 -30
  231. package/router/dist/index.js +0 -32
  232. package/router/dist/local/local-traversal.d.ts +0 -18
  233. package/router/dist/local/local-traversal.js +0 -334
  234. package/router/dist/processing/engine.d.ts +0 -132
  235. package/router/dist/processing/engine.js +0 -533
  236. package/router/dist/processing/reducers.d.ts +0 -280
  237. package/router/dist/processing/reducers.js +0 -1673
  238. package/router/dist/processing/renderers.d.ts +0 -31
  239. package/router/dist/processing/renderers.js +0 -195
  240. package/router/dist/processing/scripts.d.ts +0 -91
  241. package/router/dist/processing/scripts.js +0 -386
  242. package/router/dist/repo/repo-traversal.d.ts +0 -18
  243. package/router/dist/repo/repo-traversal.js +0 -245
  244. package/router/dist/routing/observed-reducers.d.ts +0 -41
  245. package/router/dist/routing/observed-reducers.js +0 -661
  246. package/router/dist/routing/observed-routing.d.ts +0 -26
  247. package/router/dist/routing/observed-routing.js +0 -378
  248. package/router/dist/routing/parsers.d.ts +0 -16
  249. package/router/dist/routing/parsers.js +0 -521
  250. package/router/dist/routing/run-filters.d.ts +0 -60
  251. package/router/dist/routing/run-filters.js +0 -238
  252. package/router/dist/routing/run-reducers.d.ts +0 -49
  253. package/router/dist/routing/run-reducers.js +0 -122
  254. package/router/dist/sandbox/adapter-roots.d.ts +0 -46
  255. package/router/dist/sandbox/adapter-roots.js +0 -66
  256. package/router/dist/sandbox/eryx-python-adapter.d.ts +0 -13
  257. package/router/dist/sandbox/eryx-python-adapter.js +0 -868
  258. package/router/dist/sandbox/jq-wasm-adapter.d.ts +0 -9
  259. package/router/dist/sandbox/jq-wasm-adapter.js +0 -429
  260. package/router/dist/sandbox/quickjs-wasi-adapter.d.ts +0 -13
  261. package/router/dist/sandbox/quickjs-wasi-adapter.js +0 -384
  262. package/router/dist/sandbox/script-sandbox.d.ts +0 -134
  263. package/router/dist/sandbox/script-sandbox.js +0 -337
  264. package/router/dist/setup/script-transform-adapters.d.ts +0 -32
  265. package/router/dist/setup/script-transform-adapters.js +0 -278
  266. package/router/dist/tools/batch.d.ts +0 -33
  267. package/router/dist/tools/batch.js +0 -586
  268. package/router/dist/tools/run.d.ts +0 -62
  269. package/router/dist/tools/run.js +0 -1304
  270. package/router/dist/tools/search.d.ts +0 -66
  271. package/router/dist/tools/search.js +0 -1364
  272. package/router/dist/transform/engine.d.ts +0 -168
  273. package/router/dist/transform/engine.js +0 -2072
  274. package/router/dist/vault/vault-index.d.ts +0 -125
  275. package/router/dist/vault/vault-index.js +0 -416
  276. package/router/dist/vault/vault.d.ts +0 -138
  277. package/router/dist/vault/vault.js +0 -630
  278. package/runtime/interaction-contract.md +0 -16
  279. package/skills/discuss/references/checkpoints.md +0 -66
  280. package/skills/execute-work/references/execution-loop.md +0 -77
  281. package/skills/track-work/references/working-record-schema.md +0 -378
  282. package/skills/workflow/references/workflow-loop.md +0 -92
  283. /package/skills/handoff/references/{templates.md → handoff-templates.md} +0 -0
  284. /package/skills/review-artifact/references/{reviewer-prompt.md → independent-artifact-reviewer-contract.md} +0 -0
@@ -1,38 +1,210 @@
1
- import { handleNativeToolSafetyNet } from "./output-router/native-safety-net.js";
2
- import { handleObservedToolRouting } from "./output-router/observed-tool-routing.js";
3
- import { registerRouterTools } from "./output-router/router-tools.js";
4
- import { handleFreeflowCommand, handleOutputRouterCommand } from "./settings/settings-ui.js";
1
+ import {
2
+ COGNITIVE_ROUTING_CONTROL_ENTRY,
3
+ COGNITIVE_ROUTING_INTENT_ENTRY,
4
+ CognitiveRoutingController,
5
+ } from "./cognitive-routing/controller.js";
6
+ import {
7
+ cognitiveRoutingProfileCompletions,
8
+ handleCognitiveRoutingProfileCommand,
9
+ } from "./cognitive-routing/commands.js";
10
+ import { registerCognitiveRoutingHistoryTool, registerCognitiveRoutingTool } from "./cognitive-routing/tool.js";
11
+ import { readCognitiveRoutingHistory } from "./cognitive-routing/history.js";
12
+ import { ConversationHistoryRuntime } from "./conversation-history/runtime.js";
13
+ import { FreeflowContextRuntime } from "./freeflow-context/runtime.js";
14
+ import { CONTEXT_VIRTUALIZATION_TOOL_NAME, registerFreeflowContextTool } from "./freeflow-context/tool.js";
15
+ import { handleContextCommand } from "./context-virtualization/commands.js";
16
+ import { ContextVirtualizationRuntime } from "./context-virtualization/runtime.js";
17
+ import { handleFreeflowCommand } from "./settings/settings-ui.js";
18
+ import { isPiFlowHost } from "./runtime/runtime-identity.js";
5
19
  import {
6
20
  CONTRIBUTOR_COMMANDS,
21
+ COGNITIVE_ROUTING_SWITCH_TOOL_NAME,
7
22
  WORKFLOW_COMMANDS,
8
- WORKFLOW_BOOTSTRAP_MESSAGE_TYPE,
9
- FREEFLOW_STATUS_TOOL_NAME,
10
23
  freeflowModelSkillPaths,
11
24
  freeflowSkillPath,
12
25
  getRuntimeContext,
13
- OUTPUT_ROUTER_TOOL_NAMES,
14
26
  readCapabilityState,
15
27
  readModeState,
16
- readOutputRouterConfig,
17
28
  refreshRuntimeContext,
18
29
  restoreModeOverride,
19
30
  runtimeContext,
20
- workflowBootstrapMessage,
31
+ filterBootstrapMessage,
21
32
  setModeStatus,
22
33
  skillPrompt,
23
- notifyRouterConfigWarnings,
34
+ withFreeflowRuntimeState,
24
35
  } from "./runtime/runtime-context.js";
25
36
 
26
- function isOutputRouterToolName(name: string): boolean {
27
- return OUTPUT_ROUTER_TOOL_NAMES.includes(name);
37
+ function startupSelectionSuppressesCognitiveRouting(ctx: any): boolean {
38
+ return ctx?.modelStateProvenance?.explicitModel === true || ctx?.modelStateProvenance?.explicitThinking === true;
28
39
  }
29
40
 
30
- async function applyCapabilityToolVisibility(pi: any, ctx: any, capabilityState = undefined): Promise<void> {
41
+ function unavailableCapability(capability: any, code: string, message: string): any {
42
+ return {
43
+ ...capability,
44
+ effective: false,
45
+ blockingReason: { code, message },
46
+ };
47
+ }
48
+
49
+ function modelFacingCapabilityState(
50
+ capabilityState: any,
51
+ ctx: any,
52
+ freeflowContext: any,
53
+ cognitiveRoutingController: CognitiveRoutingController | undefined,
54
+ cognitiveRoutingActivationFailed = false,
55
+ ): any {
56
+ const surfaceState = {
57
+ ...capabilityState,
58
+ interactionContract: { ...capabilityState?.interactionContract },
59
+ skills: { ...capabilityState?.skills },
60
+ contextVirtualization: { ...capabilityState?.contextVirtualization },
61
+ conversationHistory: { ...capabilityState?.conversationHistory },
62
+ cognitiveRouting: { ...capabilityState?.cognitiveRouting },
63
+ };
64
+ if (surfaceState.enabled !== true) return surfaceState;
65
+
66
+ const markUnavailable = (key: string, message: string) => {
67
+ if (surfaceState[key]?.effective === true) {
68
+ surfaceState[key] = unavailableCapability(surfaceState[key], "unavailable", message);
69
+ }
70
+ };
71
+
72
+ if (!freeflowContext?.corePrompt) {
73
+ for (const key of [
74
+ "interactionContract",
75
+ "skills",
76
+ "contextVirtualization",
77
+ "conversationHistory",
78
+ "cognitiveRouting",
79
+ ]) {
80
+ markUnavailable(key, "Freeflow core prompt is unavailable.");
81
+ }
82
+ return surfaceState;
83
+ }
84
+
85
+ if (surfaceState.interactionContract?.effective === true && !freeflowContext.interactionContractPrompt) {
86
+ markUnavailable("interactionContract", "Interaction Contract prompt is unavailable.");
87
+ }
88
+ if (surfaceState.skills?.effective === true && !freeflowContext.skillsPrompt) {
89
+ markUnavailable("skills", "Skills prompt is unavailable.");
90
+ }
91
+
92
+ if (surfaceState.skills?.effective === true) {
93
+ if (surfaceState.contextVirtualization?.effective === true && !freeflowContext.contextVirtualizationPrompt) {
94
+ markUnavailable("contextVirtualization", "Context Virtualization prompt is unavailable.");
95
+ }
96
+ if (surfaceState.conversationHistory?.effective === true && !freeflowContext.conversationHistoryPrompt) {
97
+ markUnavailable("conversationHistory", "Conversation History prompt is unavailable.");
98
+ }
99
+ } else {
100
+ for (const key of ["contextVirtualization", "conversationHistory", "cognitiveRouting"]) {
101
+ markUnavailable(key, "Skills prompt is unavailable.");
102
+ }
103
+ }
104
+
105
+ if (surfaceState.cognitiveRouting?.effective === true) {
106
+ if (startupSelectionSuppressesCognitiveRouting(ctx)) {
107
+ surfaceState.cognitiveRouting = unavailableCapability(
108
+ surfaceState.cognitiveRouting,
109
+ "runtime_inactive",
110
+ "Cognitive Routing is inactive because the host selected the startup model or thinking level.",
111
+ );
112
+ } else if (cognitiveRoutingActivationFailed || cognitiveRoutingController?.state()?.effective === false) {
113
+ surfaceState.cognitiveRouting = unavailableCapability(
114
+ surfaceState.cognitiveRouting,
115
+ "unavailable",
116
+ "Cognitive Routing could not activate for this session.",
117
+ );
118
+ } else if (!freeflowContext.cognitiveRoutingPrompt) {
119
+ markUnavailable("cognitiveRouting", "Cognitive Routing prompt is unavailable.");
120
+ }
121
+ }
122
+
123
+ return surfaceState;
124
+ }
125
+
126
+ function modelFacingModeState(modeState: any, capabilityState: any): any {
127
+ if (capabilityState?.skills?.effective === true) return modeState;
128
+ return { ...modeState, active: false, effectiveMode: null };
129
+ }
130
+
131
+ type SessionEntriesContext = {
132
+ sessionManager?: {
133
+ getBranch?: () => readonly unknown[];
134
+ getEntries?: () => readonly unknown[];
135
+ };
136
+ };
137
+
138
+ function sessionHasConversationOrRoutingState(ctx: SessionEntriesContext | undefined): boolean {
139
+ try {
140
+ const entries = ctx?.sessionManager?.getBranch?.() ?? ctx?.sessionManager?.getEntries?.() ?? [];
141
+ if (!Array.isArray(entries)) return false;
142
+ return entries.some((entry: unknown) => {
143
+ if (!entry || typeof entry !== "object") return false;
144
+ const record = entry as { type?: unknown; customType?: unknown };
145
+ if (
146
+ typeof record.type === "string" &&
147
+ ["message", "custom_message", "compaction", "branch_summary"].includes(record.type)
148
+ ) {
149
+ return true;
150
+ }
151
+ return (
152
+ record.type === "custom" &&
153
+ (record.customType === COGNITIVE_ROUTING_INTENT_ENTRY || record.customType === COGNITIVE_ROUTING_CONTROL_ENTRY)
154
+ );
155
+ });
156
+ } catch {
157
+ return false;
158
+ }
159
+ }
160
+
161
+ function hasCognitiveRoutingHost(pi: any, ctx: any): boolean {
162
+ return (
163
+ isPiFlowHost(pi?.host) &&
164
+ typeof pi?.appendEntryDurable === "function" &&
165
+ typeof pi?.acquireModelStateControl === "function" &&
166
+ typeof ctx?.modelRegistry?.getApiKeyAndHeaders === "function"
167
+ );
168
+ }
169
+
170
+ async function reconcileCognitiveRoutingController(
171
+ pi: any,
172
+ ctx: any,
173
+ capabilityState: any,
174
+ previous: CognitiveRoutingController | undefined,
175
+ ): Promise<CognitiveRoutingController | undefined> {
176
+ const cognitiveRouting = capabilityState?.cognitiveRouting;
177
+ if (
178
+ !isPiFlowHost(pi?.host) ||
179
+ !cognitiveRouting?.effective ||
180
+ startupSelectionSuppressesCognitiveRouting(ctx) ||
181
+ !hasCognitiveRoutingHost(pi, ctx)
182
+ ) {
183
+ if (previous) await previous.deactivate();
184
+ return undefined;
185
+ }
186
+
187
+ const controller = new CognitiveRoutingController({ capabilityState: cognitiveRouting, pi, ctx });
188
+ const recovered = await controller.recover();
189
+ if (recovered.status === "pending") return controller;
190
+ if (recovered.status !== "active") {
191
+ const activated = await controller.activate();
192
+ return activated.status === "active" ? controller : undefined;
193
+ }
194
+ return controller;
195
+ }
196
+
197
+ async function applyCapabilityToolVisibility(
198
+ pi: any,
199
+ ctx: any,
200
+ capabilityState = undefined,
201
+ cognitiveRoutingController: CognitiveRoutingController | undefined = undefined,
202
+ ): Promise<void> {
31
203
  if (typeof pi?.setActiveTools !== "function" || typeof pi?.getAllTools !== "function") {
32
204
  return;
33
205
  }
34
206
 
35
- const state = capabilityState ?? (await readCapabilityState(ctx.cwd));
207
+ const state = capabilityState ?? (await readCapabilityState(ctx.cwd, ctx, pi?.host));
36
208
  const allToolNames = pi
37
209
  .getAllTools()
38
210
  .map((tool: any) => tool?.name)
@@ -43,25 +215,49 @@ async function applyCapabilityToolVisibility(pi: any, ctx: any, capabilityState
43
215
  (Array.isArray(currentActive) ? currentActive : allToolNames).filter((name: string) => allToolNameSet.has(name)),
44
216
  );
45
217
 
46
- if (allToolNameSet.has(FREEFLOW_STATUS_TOOL_NAME)) {
47
- if (state.configured && state.enabled) active.add(FREEFLOW_STATUS_TOOL_NAME);
48
- else active.delete(FREEFLOW_STATUS_TOOL_NAME);
218
+ if (allToolNameSet.has(COGNITIVE_ROUTING_SWITCH_TOOL_NAME)) {
219
+ const controllerState = cognitiveRoutingController?.state();
220
+ const routingToolActive =
221
+ state.cognitiveRouting?.effective === true &&
222
+ controllerState?.effective === true &&
223
+ controllerState.controlMode === "automatic" &&
224
+ !startupSelectionSuppressesCognitiveRouting(ctx);
225
+ if (routingToolActive) active.add(COGNITIVE_ROUTING_SWITCH_TOOL_NAME);
226
+ else active.delete(COGNITIVE_ROUTING_SWITCH_TOOL_NAME);
49
227
  }
50
228
 
51
- for (const toolName of OUTPUT_ROUTER_TOOL_NAMES) {
52
- if (!allToolNameSet.has(toolName)) continue;
53
- if (state.outputRouter.enabled) active.add(toolName);
54
- else active.delete(toolName);
229
+ if (allToolNameSet.has(CONTEXT_VIRTUALIZATION_TOOL_NAME)) {
230
+ if (state.contextVirtualization?.effective === true || state.conversationHistory?.effective === true) {
231
+ active.add(CONTEXT_VIRTUALIZATION_TOOL_NAME);
232
+ } else {
233
+ active.delete(CONTEXT_VIRTUALIZATION_TOOL_NAME);
234
+ }
55
235
  }
56
236
 
57
237
  pi.setActiveTools([...active]);
58
238
  }
59
239
 
60
- async function applyLiveCapabilityState(pi: any, ctx: any): Promise<void> {
61
- const [modeState, capabilityState] = await Promise.all([readModeState(ctx.cwd), readCapabilityState(ctx.cwd)]);
240
+ async function applyLiveCapabilityState(
241
+ pi: any,
242
+ ctx: any,
243
+ cognitiveRoutingController: CognitiveRoutingController | undefined,
244
+ options: { reconcileCognitiveRouting?: boolean } = {},
245
+ ): Promise<CognitiveRoutingController | undefined> {
246
+ const [modeState, capabilityState] = await Promise.all([
247
+ readModeState(ctx.cwd),
248
+ readCapabilityState(ctx.cwd, ctx, pi?.host),
249
+ ]);
62
250
  await refreshRuntimeContext(capabilityState);
63
- setModeStatus(ctx, modeState, capabilityState);
64
- await applyCapabilityToolVisibility(pi, ctx, capabilityState);
251
+ let nextController = cognitiveRoutingController;
252
+ if (
253
+ options.reconcileCognitiveRouting &&
254
+ (nextController === undefined || capabilityState.cognitiveRouting?.effective !== true)
255
+ ) {
256
+ nextController = await reconcileCognitiveRoutingController(pi, ctx, capabilityState, nextController);
257
+ }
258
+ setModeStatus(ctx, modeState, capabilityState, nextController?.state());
259
+ await applyCapabilityToolVisibility(pi, ctx, capabilityState, nextController);
260
+ return nextController;
65
261
  }
66
262
 
67
263
  function disabledToolCall(toolName: string, capability: string) {
@@ -72,17 +268,7 @@ function disabledToolCall(toolName: string, capability: string) {
72
268
  };
73
269
  }
74
270
 
75
- function capabilityCompletions(prefix: string | undefined) {
76
- const query = prefix ?? "";
77
- return [
78
- { value: "settings", label: "settings", description: "Open repository Output Router settings" },
79
- { value: "status", label: "status", description: "Show effective Output Router state" },
80
- { value: "enable", label: "enable", description: "Enable Output Router for this repository" },
81
- { value: "disable", label: "disable", description: "Disable Output Router for this repository" },
82
- ].filter((item) => item.value.startsWith(query));
83
- }
84
-
85
- function freeflowCompletions(prefix: string | undefined) {
271
+ function freeflowCompletions(prefix: string | undefined, hostInfo = undefined) {
86
272
  const query = prefix ?? "";
87
273
  if (query.startsWith("settings ")) {
88
274
  const settingsQuery = query.slice("settings ".length);
@@ -94,6 +280,12 @@ function freeflowCompletions(prefix: string | undefined) {
94
280
  .filter((item) => item.value.startsWith(settingsQuery))
95
281
  .map((item) => ({ ...item, value: `settings ${item.value}` }));
96
282
  }
283
+ if (isPiFlowHost(hostInfo) && query.startsWith("profile ")) {
284
+ return cognitiveRoutingProfileCompletions(query.slice("profile ".length)).map((item) => ({
285
+ ...item,
286
+ value: `profile ${item.value}`,
287
+ }));
288
+ }
97
289
  if (query.startsWith("mode ")) {
98
290
  const modeQuery = query.slice("mode ".length);
99
291
  return [
@@ -109,10 +301,25 @@ function freeflowCompletions(prefix: string | undefined) {
109
301
  .filter((item) => item.value.startsWith(modeQuery))
110
302
  .map((item) => ({ ...item, value: `mode ${item.value}` }));
111
303
  }
304
+ if (query.startsWith("context ")) {
305
+ const contextQuery = query.slice("context ".length);
306
+ return [
307
+ { value: "status", label: "status", description: "Show Freeflow Context state" },
308
+ { value: "list", label: "list", description: "List archived context projections" },
309
+ { value: "restore", label: "restore", description: "Restore one or more context references" },
310
+ { value: "reset all", label: "reset all", description: "Reset projection decisions on the active branch" },
311
+ ]
312
+ .filter((item) => item.value.startsWith(contextQuery))
313
+ .map((item) => ({ ...item, value: `context ${item.value}` }));
314
+ }
112
315
  return [
113
316
  { value: "settings", label: "settings", description: "Open personal override settings" },
114
317
  { value: "status", label: "status", description: "Show effective Freeflow state" },
318
+ { value: "context", label: "context", description: "Inspect Freeflow Context" },
115
319
  { value: "mode", label: "mode", description: "Select a temporary session mode" },
320
+ ...(isPiFlowHost(hostInfo)
321
+ ? [{ value: "profile", label: "profile", description: "Hold or release Cognitive Routing profile control" }]
322
+ : []),
116
323
  { value: "enable", label: "enable", description: "Enable Freeflow for this repository" },
117
324
  { value: "disable", label: "disable", description: "Disable Freeflow for this repository" },
118
325
  ].filter((item) => item.value.startsWith(query));
@@ -127,7 +334,7 @@ function bypassCompletions(prefix: string | undefined) {
127
334
  }
128
335
 
129
336
  async function sendSkillCommand(pi: any, ctx: any, skill: string, args: string | undefined) {
130
- const state = await readCapabilityState(ctx.cwd);
337
+ const state = await readCapabilityState(ctx.cwd, ctx, pi?.host);
131
338
  if (skill === "setup-freeflow" && !state.configured) {
132
339
  await pi.sendUserMessage(skillPrompt(skill, args));
133
340
  return;
@@ -151,102 +358,322 @@ async function sendSkillCommand(pi: any, ctx: any, skill: string, args: string |
151
358
  }
152
359
 
153
360
  export default function freeflow(pi) {
154
- registerRouterTools(pi);
361
+ let cognitiveRoutingController: CognitiveRoutingController | undefined;
362
+ let latestCognitiveRoutingContext: any;
363
+ let providerSurfaceSnapshot: { context: any; value: any } | undefined;
364
+ let freeflowContextRuntime: FreeflowContextRuntime | undefined;
365
+ let contextVirtualizationRuntime: ContextVirtualizationRuntime | undefined;
366
+ let conversationHistoryRuntime: ConversationHistoryRuntime | undefined;
367
+ const registerContextToolForState = (capabilityState: any) => {
368
+ registerFreeflowContextTool(
369
+ pi,
370
+ () => contextVirtualizationRuntime,
371
+ () => conversationHistoryRuntime,
372
+ {
373
+ contextVirtualization: capabilityState?.contextVirtualization?.effective === true,
374
+ conversationHistory: capabilityState?.conversationHistory?.effective === true,
375
+ },
376
+ );
377
+ };
378
+ const buildProviderSurface = async (ctx: any, activateCognitiveRouting = false): Promise<any> => {
379
+ const [modeState, capabilityState] = await Promise.all([
380
+ readModeState(ctx.cwd),
381
+ readCapabilityState(ctx.cwd, ctx, pi?.host),
382
+ ]);
383
+ const freeflowContext = await getRuntimeContext(capabilityState);
384
+ const promptCapabilityState = modelFacingCapabilityState(
385
+ capabilityState,
386
+ ctx,
387
+ freeflowContext,
388
+ cognitiveRoutingController,
389
+ );
390
+ let activationAttempted = false;
391
+ if (
392
+ activateCognitiveRouting &&
393
+ (cognitiveRoutingController === undefined || promptCapabilityState.cognitiveRouting?.effective !== true)
394
+ ) {
395
+ activationAttempted =
396
+ promptCapabilityState.cognitiveRouting?.effective === true && !startupSelectionSuppressesCognitiveRouting(ctx);
397
+ try {
398
+ cognitiveRoutingController = await reconcileCognitiveRoutingController(
399
+ pi,
400
+ ctx,
401
+ promptCapabilityState,
402
+ cognitiveRoutingController,
403
+ );
404
+ } catch {
405
+ cognitiveRoutingController = undefined;
406
+ }
407
+ }
408
+ const surfaceCapabilityState = modelFacingCapabilityState(
409
+ promptCapabilityState,
410
+ ctx,
411
+ freeflowContext,
412
+ cognitiveRoutingController,
413
+ activationAttempted && !cognitiveRoutingController,
414
+ );
415
+ return {
416
+ modeState: modelFacingModeState(modeState, surfaceCapabilityState),
417
+ capabilityState: surfaceCapabilityState,
418
+ freeflowContext,
419
+ cognitiveRoutingRuntime: cognitiveRoutingController?.state(),
420
+ configuredCapabilityState: capabilityState,
421
+ };
422
+ };
423
+ const applyLiveCapabilityStateForSession = async (
424
+ ctx: any,
425
+ options: { reconcileCognitiveRouting?: boolean } = {},
426
+ ): Promise<void> => {
427
+ cognitiveRoutingController = await applyLiveCapabilityState(pi, ctx, cognitiveRoutingController, options);
428
+ registerContextToolForState(await readCapabilityState(ctx.cwd, ctx, pi?.host));
429
+ };
430
+
431
+ if (isPiFlowHost(pi?.host)) {
432
+ registerCognitiveRoutingTool(pi, () => cognitiveRoutingController);
433
+ registerCognitiveRoutingHistoryTool(pi, (options, context) => {
434
+ if (cognitiveRoutingController) return cognitiveRoutingController.history(options);
435
+ return readCognitiveRoutingHistory(context ?? latestCognitiveRoutingContext, options);
436
+ });
437
+ }
438
+ registerFreeflowContextTool(
439
+ pi,
440
+ () => contextVirtualizationRuntime,
441
+ () => conversationHistoryRuntime,
442
+ { contextVirtualization: false, conversationHistory: false },
443
+ );
444
+
445
+ if (isPiFlowHost(pi?.host) && typeof pi.registerShortcut === "function") {
446
+ pi.registerShortcut("ctrl+shift+r", {
447
+ description: "Cycle the Cognitive Routing manual standard/reasoning hold",
448
+ handler: async (ctx) => {
449
+ if (typeof ctx?.isIdle === "function" && !ctx.isIdle()) {
450
+ ctx.ui?.notify?.("Freeflow settings and profile changes are available only while Pi is idle.", "warning");
451
+ return;
452
+ }
453
+ if (!cognitiveRoutingController) {
454
+ await applyLiveCapabilityStateForSession(ctx, { reconcileCognitiveRouting: true });
455
+ }
456
+ const controller = cognitiveRoutingController;
457
+ if (!controller) {
458
+ ctx.ui?.notify?.("Cognitive Routing is unavailable for this session.", "warning");
459
+ return;
460
+ }
461
+ const current = controller.state().activeProfile;
462
+ const target = current === "reasoning" ? "standard" : "reasoning";
463
+ const result = await controller.setManualProfile(target, "profile-shortcut");
464
+ if (result.status === "active") {
465
+ ctx.ui?.notify?.(`Cognitive Routing manual hold set to ${target}.`, "info");
466
+ } else {
467
+ ctx.ui?.notify?.(`Cognitive Routing could not set the manual profile: ${result.reason}.`, "warning");
468
+ }
469
+ await applyLiveCapabilityStateForSession(ctx);
470
+ },
471
+ });
472
+ pi.registerShortcut("ctrl+shift+a", {
473
+ description: "Cycle the Cognitive Routing automatic standard/reasoning profile",
474
+ handler: async (ctx) => {
475
+ if (typeof ctx?.isIdle === "function" && !ctx.isIdle()) {
476
+ ctx.ui?.notify?.("Freeflow settings and profile changes are available only while Pi is idle.", "warning");
477
+ return;
478
+ }
479
+ if (!cognitiveRoutingController) {
480
+ await applyLiveCapabilityStateForSession(ctx, { reconcileCognitiveRouting: true });
481
+ }
482
+ const controller = cognitiveRoutingController;
483
+ if (!controller) {
484
+ ctx.ui?.notify?.("Cognitive Routing is unavailable for this session.", "warning");
485
+ return;
486
+ }
487
+ const state = controller.state();
488
+ const target = state.activeProfile === "reasoning" ? "standard" : "reasoning";
489
+ const result =
490
+ state.controlMode === "automatic" && state.activeProfile
491
+ ? await controller.switchAutomaticProfile(
492
+ target,
493
+ `Cycle automatic profile to ${target}.`,
494
+ "user",
495
+ "profile-shortcut",
496
+ )
497
+ : await controller.setAutomaticControl("profile-shortcut");
498
+ if (result.status === "automatic") {
499
+ ctx.ui?.notify?.("Cognitive Routing automatic control active.", "info");
500
+ } else if (result.status === "active") {
501
+ ctx.ui?.notify?.(`Cognitive Routing automatic profile set to ${result.profile}.`, "info");
502
+ } else {
503
+ ctx.ui?.notify?.(`Cognitive Routing could not cycle the automatic profile: ${result.reason}.`, "warning");
504
+ }
505
+ await applyLiveCapabilityStateForSession(ctx);
506
+ },
507
+ });
508
+ }
155
509
 
156
510
  pi.on("resources_discover", async (event, ctx) => {
157
511
  const cwd = ctx?.cwd ?? event?.cwd ?? process.cwd();
158
- const state = await readCapabilityState(cwd);
512
+ const snapshot =
513
+ providerSurfaceSnapshot?.context === ctx
514
+ ? providerSurfaceSnapshot.value
515
+ : await buildProviderSurface(ctx ?? { cwd }, false);
516
+ const state = snapshot.capabilityState;
159
517
  if (!state.configured) {
160
518
  return { skillPaths: [freeflowSkillPath("setup-freeflow")] };
161
519
  }
162
520
  if (!state.enabled || !state.skills.effective) {
163
521
  return { skillPaths: [] };
164
522
  }
165
- return { skillPaths: freeflowModelSkillPaths() };
523
+ return { skillPaths: freeflowModelSkillPaths(state) };
166
524
  });
167
525
 
168
526
  pi.on("session_start", async (_event, ctx) => {
527
+ latestCognitiveRoutingContext = ctx;
528
+ providerSurfaceSnapshot = undefined;
169
529
  restoreModeOverride(ctx);
170
- const [modeState, routerConfigResult, capabilityState] = await Promise.all([
171
- readModeState(ctx.cwd),
172
- readOutputRouterConfig(ctx.cwd),
173
- readCapabilityState(ctx.cwd),
174
- ]);
530
+ freeflowContextRuntime = new FreeflowContextRuntime(ctx);
531
+ contextVirtualizationRuntime = new ContextVirtualizationRuntime(pi, ctx, freeflowContextRuntime);
532
+ conversationHistoryRuntime = new ConversationHistoryRuntime(
533
+ ctx,
534
+ (entryId) => contextVirtualizationRuntime?.isSourceFullyProjected(entryId) ?? true,
535
+ freeflowContextRuntime,
536
+ );
537
+ await contextVirtualizationRuntime.recover(ctx);
538
+ const capabilityState = await readCapabilityState(ctx.cwd, ctx, pi?.host);
175
539
  await refreshRuntimeContext(capabilityState);
176
- setModeStatus(ctx, modeState, capabilityState);
177
- notifyRouterConfigWarnings(ctx, routerConfigResult);
178
- await applyCapabilityToolVisibility(pi, ctx, capabilityState);
540
+ const hasSessionState = sessionHasConversationOrRoutingState(ctx);
541
+ const snapshot = await buildProviderSurface(ctx, hasSessionState);
542
+ const cognitiveRoutingStartupPending =
543
+ snapshot.capabilityState?.cognitiveRouting?.effective === true &&
544
+ !hasSessionState &&
545
+ !startupSelectionSuppressesCognitiveRouting(ctx);
546
+ registerContextToolForState(snapshot.capabilityState);
547
+ setModeStatus(ctx, snapshot.modeState, snapshot.capabilityState, snapshot.cognitiveRoutingRuntime, {
548
+ cognitiveRoutingStartupPending,
549
+ });
550
+ await applyCapabilityToolVisibility(pi, ctx, snapshot.capabilityState, cognitiveRoutingController);
551
+ });
552
+
553
+ pi.on("agent_settled", async (_event, ctx) => {
554
+ if (!cognitiveRoutingController) return undefined;
555
+ await applyLiveCapabilityStateForSession(ctx);
556
+ return undefined;
557
+ });
558
+
559
+ pi.on("session_shutdown", async (event) => {
560
+ providerSurfaceSnapshot = undefined;
561
+ const controller = cognitiveRoutingController;
562
+ cognitiveRoutingController = undefined;
563
+ freeflowContextRuntime = undefined;
564
+ contextVirtualizationRuntime = undefined;
565
+ conversationHistoryRuntime = undefined;
566
+ if (controller) await controller.shutdown(event?.reason);
179
567
  });
180
568
 
181
569
  pi.on("session_tree", async (_event, ctx) => {
570
+ latestCognitiveRoutingContext = ctx;
571
+ providerSurfaceSnapshot = undefined;
182
572
  restoreModeOverride(ctx);
183
- await applyLiveCapabilityState(pi, ctx);
573
+ const controller = cognitiveRoutingController;
574
+ if (controller) await controller.reconcileBranch();
575
+ if (contextVirtualizationRuntime) {
576
+ contextVirtualizationRuntime.setContext(ctx);
577
+ await contextVirtualizationRuntime.recover(ctx);
578
+ }
579
+ conversationHistoryRuntime?.setContext(ctx);
580
+ await applyLiveCapabilityStateForSession(ctx);
184
581
  });
185
582
 
186
583
  pi.on("session_compact", async (_event, ctx) => {
187
- const [modeState, routerConfigResult, capabilityState] = await Promise.all([
584
+ latestCognitiveRoutingContext = ctx;
585
+ providerSurfaceSnapshot = undefined;
586
+ const controller = cognitiveRoutingController;
587
+ if (controller) await controller.reconcileBranch("session-compact");
588
+ if (contextVirtualizationRuntime) {
589
+ contextVirtualizationRuntime.setContext(ctx);
590
+ await contextVirtualizationRuntime.recover(ctx);
591
+ }
592
+ conversationHistoryRuntime?.setContext(ctx);
593
+ const [modeState, capabilityState] = await Promise.all([
188
594
  readModeState(ctx.cwd),
189
- readOutputRouterConfig(ctx.cwd),
190
- readCapabilityState(ctx.cwd),
595
+ readCapabilityState(ctx.cwd, ctx, pi?.host),
191
596
  ]);
192
597
  await refreshRuntimeContext(capabilityState);
193
- setModeStatus(ctx, modeState, capabilityState);
194
- notifyRouterConfigWarnings(ctx, routerConfigResult);
195
- await applyCapabilityToolVisibility(pi, ctx, capabilityState);
598
+ registerContextToolForState(capabilityState);
599
+ setModeStatus(ctx, modeState, capabilityState, cognitiveRoutingController?.state());
600
+ await applyCapabilityToolVisibility(pi, ctx, capabilityState, cognitiveRoutingController);
196
601
  });
197
602
 
198
603
  pi.on("before_agent_start", async (event, ctx) => {
199
- const [modeState, routerConfigResult, capabilityState] = await Promise.all([
200
- readModeState(ctx.cwd),
201
- readOutputRouterConfig(ctx.cwd),
202
- readCapabilityState(ctx.cwd),
203
- ]);
204
- const freeflowContext = await getRuntimeContext(capabilityState);
205
- setModeStatus(ctx, modeState, capabilityState);
206
- notifyRouterConfigWarnings(ctx, routerConfigResult);
207
- await applyCapabilityToolVisibility(pi, ctx, capabilityState);
208
- const freeflowRuntimeContext = runtimeContext(modeState, freeflowContext, routerConfigResult, capabilityState);
209
- const workflowMessage = workflowBootstrapMessage(freeflowContext, capabilityState, ctx.sessionManager);
604
+ latestCognitiveRoutingContext = ctx;
605
+ const snapshot = await buildProviderSurface(ctx, true);
606
+ providerSurfaceSnapshot = { context: ctx, value: snapshot };
607
+ registerContextToolForState(snapshot.capabilityState);
608
+ setModeStatus(ctx, snapshot.modeState, snapshot.capabilityState, snapshot.cognitiveRoutingRuntime);
609
+ await applyCapabilityToolVisibility(pi, ctx, snapshot.capabilityState, cognitiveRoutingController);
610
+ const freeflowRuntimeContext = runtimeContext(snapshot.freeflowContext, snapshot.capabilityState);
210
611
  const systemPrompt = freeflowRuntimeContext
211
612
  ? `${event.systemPrompt}\n\n${freeflowRuntimeContext}`
212
613
  : event.systemPrompt;
213
- return { message: workflowMessage, systemPrompt };
614
+ return { systemPrompt };
214
615
  });
215
616
 
216
617
  pi.on("context", async (event, ctx) => {
217
- const capabilityState = await readCapabilityState(ctx.cwd);
218
- if (capabilityState.skills.effective) {
219
- return undefined;
618
+ const snapshot =
619
+ providerSurfaceSnapshot?.context === ctx ? providerSurfaceSnapshot.value : await buildProviderSurface(ctx, false);
620
+ if (providerSurfaceSnapshot?.context === ctx) providerSurfaceSnapshot = undefined;
621
+ const cognitiveRoutingRuntime = snapshot.cognitiveRoutingRuntime;
622
+ const surfaceCapabilityState = snapshot.capabilityState;
623
+ const surfaceModeState = snapshot.modeState;
624
+ let changed = false;
625
+ let messages = event.messages
626
+ .map((message) => {
627
+ const filtered = filterBootstrapMessage(message);
628
+ if (filtered !== message) changed = true;
629
+ return filtered;
630
+ })
631
+ .filter((message) => message !== undefined);
632
+ if (contextVirtualizationRuntime) {
633
+ contextVirtualizationRuntime.setContext(ctx);
634
+ const projected = await contextVirtualizationRuntime.project(
635
+ messages,
636
+ surfaceCapabilityState.contextVirtualization?.effective === true,
637
+ );
638
+ if (projected.changed) {
639
+ changed = true;
640
+ messages = projected.messages;
641
+ }
220
642
  }
221
-
222
- const messages = event.messages.filter(
223
- (message) => !(message?.role === "custom" && message?.customType === WORKFLOW_BOOTSTRAP_MESSAGE_TYPE),
643
+ if (conversationHistoryRuntime && surfaceCapabilityState.conversationHistory?.effective === true) {
644
+ conversationHistoryRuntime.setContext(ctx);
645
+ conversationHistoryRuntime.capture(surfaceCapabilityState.contextVirtualization?.effective === true);
646
+ }
647
+ const nextMessages = withFreeflowRuntimeState(
648
+ messages,
649
+ surfaceModeState,
650
+ surfaceCapabilityState,
651
+ cognitiveRoutingRuntime,
224
652
  );
225
- return messages.length === event.messages.length ? undefined : { messages };
653
+ changed = true;
654
+ messages = nextMessages;
655
+ return changed ? { messages } : undefined;
226
656
  });
227
657
 
228
658
  pi.on("tool_call", async (event, ctx) => {
229
- const capabilityState = await readCapabilityState(ctx.cwd);
659
+ const capabilityState = await readCapabilityState(ctx.cwd, ctx, pi?.host);
230
660
  const toolName = typeof event?.toolName === "string" ? event.toolName : "";
231
- if ((!capabilityState.configured || !capabilityState.enabled) && toolName === FREEFLOW_STATUS_TOOL_NAME) {
232
- return disabledToolCall(toolName, "freeflow");
233
- }
234
- if (!capabilityState.outputRouter.enabled && isOutputRouterToolName(toolName)) {
235
- return disabledToolCall(toolName, "output-router");
661
+ if (
662
+ capabilityState.contextVirtualization?.effective !== true &&
663
+ capabilityState.conversationHistory?.effective !== true &&
664
+ toolName === CONTEXT_VIRTUALIZATION_TOOL_NAME
665
+ ) {
666
+ return disabledToolCall(toolName, "context");
236
667
  }
237
668
  return undefined;
238
669
  });
239
670
 
240
671
  pi.on("tool_result", async (event, ctx) => {
241
- const capabilityState = await readCapabilityState(ctx.cwd);
242
- if (!capabilityState.outputRouter.enabled) {
243
- return undefined;
244
- }
245
- const observed = await handleObservedToolRouting(event, ctx);
246
- if (observed) {
247
- return observed;
672
+ const toolName = typeof event?.toolName === "string" ? event.toolName : "";
673
+ if (isPiFlowHost(pi?.host) && toolName === COGNITIVE_ROUTING_SWITCH_TOOL_NAME) {
674
+ await applyLiveCapabilityStateForSession(ctx);
248
675
  }
249
- return handleNativeToolSafetyNet(event, ctx);
676
+ return undefined;
250
677
  });
251
678
 
252
679
  for (const { command, skill } of WORKFLOW_COMMANDS) {
@@ -270,26 +697,51 @@ export default function freeflow(pi) {
270
697
 
271
698
  pi.registerCommand("freeflow", {
272
699
  description: "Open unified Freeflow settings or print compact status",
273
- getArgumentCompletions: freeflowCompletions,
700
+ getArgumentCompletions: (prefix) => freeflowCompletions(prefix, pi?.host),
274
701
  handler: async (args, ctx) => {
702
+ const contextInput = (args ?? "").trim();
703
+ if (contextInput === "context" || contextInput.startsWith("context ")) {
704
+ const capabilityState = await readCapabilityState(ctx.cwd, ctx, pi?.host);
705
+ await handleContextCommand(
706
+ contextInput.slice("context".length).trim(),
707
+ ctx,
708
+ contextVirtualizationRuntime,
709
+ capabilityState.contextVirtualization?.effective === true,
710
+ capabilityState.conversationHistory?.effective === true,
711
+ );
712
+ return;
713
+ }
714
+ if (isPiFlowHost(pi?.host) && /^profile(?:\s|$)/i.test((args ?? "").trim())) {
715
+ const profileCommandContext = {
716
+ isIdle: ctx?.isIdle,
717
+ ui: ctx?.ui,
718
+ history: (options) =>
719
+ cognitiveRoutingController?.history(options) ?? readCognitiveRoutingHistory(ctx, options),
720
+ };
721
+ const historyCommand = /^profile\s+history(?:\s|$)/i.test((args ?? "").trim());
722
+ if (historyCommand) {
723
+ await handleCognitiveRoutingProfileCommand(args, profileCommandContext, cognitiveRoutingController);
724
+ return;
725
+ }
726
+ if (!cognitiveRoutingController) {
727
+ await applyLiveCapabilityStateForSession(ctx, { reconcileCognitiveRouting: true });
728
+ }
729
+ if (await handleCognitiveRoutingProfileCommand(args, profileCommandContext, cognitiveRoutingController)) {
730
+ await applyLiveCapabilityStateForSession(ctx);
731
+ return;
732
+ }
733
+ }
275
734
  await handleFreeflowCommand(
276
735
  args,
277
736
  ctx,
278
- async () => {
279
- await applyLiveCapabilityState(pi, ctx);
737
+ async (_changed, options = {}) => {
738
+ await applyLiveCapabilityStateForSession(ctx, {
739
+ reconcileCognitiveRouting: options.reconcileCognitiveRouting ?? true,
740
+ });
280
741
  },
281
742
  pi,
743
+ cognitiveRoutingController,
282
744
  );
283
745
  },
284
746
  });
285
-
286
- pi.registerCommand("output-router", {
287
- description: "Open Freeflow Output Router settings or print compact status",
288
- getArgumentCompletions: capabilityCompletions,
289
- handler: async (args, ctx) => {
290
- await handleOutputRouterCommand(args, ctx, async () => {
291
- await applyLiveCapabilityState(pi, ctx);
292
- });
293
- },
294
- });
295
747
  }