@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,35 +1,182 @@
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
- function isOutputRouterToolName(name) {
26
- return OUTPUT_ROUTER_TOOL_NAMES.includes(name);
36
+ function startupSelectionSuppressesCognitiveRouting(ctx) {
37
+ return ctx?.modelStateProvenance?.explicitModel === true || ctx?.modelStateProvenance?.explicitThinking === true;
38
+ }
39
+ function unavailableCapability(capability, code, message) {
40
+ return {
41
+ ...capability,
42
+ effective: false,
43
+ blockingReason: { code, message },
44
+ };
45
+ }
46
+ function modelFacingCapabilityState(
47
+ capabilityState,
48
+ ctx,
49
+ freeflowContext,
50
+ cognitiveRoutingController,
51
+ cognitiveRoutingActivationFailed = false,
52
+ ) {
53
+ const surfaceState = {
54
+ ...capabilityState,
55
+ interactionContract: { ...capabilityState?.interactionContract },
56
+ skills: { ...capabilityState?.skills },
57
+ contextVirtualization: { ...capabilityState?.contextVirtualization },
58
+ conversationHistory: { ...capabilityState?.conversationHistory },
59
+ cognitiveRouting: { ...capabilityState?.cognitiveRouting },
60
+ };
61
+ if (surfaceState.enabled !== true) return surfaceState;
62
+ const markUnavailable = (key, message) => {
63
+ if (surfaceState[key]?.effective === true) {
64
+ surfaceState[key] = unavailableCapability(surfaceState[key], "unavailable", message);
65
+ }
66
+ };
67
+ if (!freeflowContext?.corePrompt) {
68
+ for (const key of [
69
+ "interactionContract",
70
+ "skills",
71
+ "contextVirtualization",
72
+ "conversationHistory",
73
+ "cognitiveRouting",
74
+ ]) {
75
+ markUnavailable(key, "Freeflow core prompt is unavailable.");
76
+ }
77
+ return surfaceState;
78
+ }
79
+ if (surfaceState.interactionContract?.effective === true && !freeflowContext.interactionContractPrompt) {
80
+ markUnavailable("interactionContract", "Interaction Contract prompt is unavailable.");
81
+ }
82
+ if (surfaceState.skills?.effective === true && !freeflowContext.skillsPrompt) {
83
+ markUnavailable("skills", "Skills prompt is unavailable.");
84
+ }
85
+ if (surfaceState.skills?.effective === true) {
86
+ if (surfaceState.contextVirtualization?.effective === true && !freeflowContext.contextVirtualizationPrompt) {
87
+ markUnavailable("contextVirtualization", "Context Virtualization prompt is unavailable.");
88
+ }
89
+ if (surfaceState.conversationHistory?.effective === true && !freeflowContext.conversationHistoryPrompt) {
90
+ markUnavailable("conversationHistory", "Conversation History prompt is unavailable.");
91
+ }
92
+ } else {
93
+ for (const key of ["contextVirtualization", "conversationHistory", "cognitiveRouting"]) {
94
+ markUnavailable(key, "Skills prompt is unavailable.");
95
+ }
96
+ }
97
+ if (surfaceState.cognitiveRouting?.effective === true) {
98
+ if (startupSelectionSuppressesCognitiveRouting(ctx)) {
99
+ surfaceState.cognitiveRouting = unavailableCapability(
100
+ surfaceState.cognitiveRouting,
101
+ "runtime_inactive",
102
+ "Cognitive Routing is inactive because the host selected the startup model or thinking level.",
103
+ );
104
+ } else if (cognitiveRoutingActivationFailed || cognitiveRoutingController?.state()?.effective === false) {
105
+ surfaceState.cognitiveRouting = unavailableCapability(
106
+ surfaceState.cognitiveRouting,
107
+ "unavailable",
108
+ "Cognitive Routing could not activate for this session.",
109
+ );
110
+ } else if (!freeflowContext.cognitiveRoutingPrompt) {
111
+ markUnavailable("cognitiveRouting", "Cognitive Routing prompt is unavailable.");
112
+ }
113
+ }
114
+ return surfaceState;
27
115
  }
28
- async function applyCapabilityToolVisibility(pi, ctx, capabilityState = undefined) {
116
+ function modelFacingModeState(modeState, capabilityState) {
117
+ if (capabilityState?.skills?.effective === true) return modeState;
118
+ return { ...modeState, active: false, effectiveMode: null };
119
+ }
120
+ function sessionHasConversationOrRoutingState(ctx) {
121
+ try {
122
+ const entries = ctx?.sessionManager?.getBranch?.() ?? ctx?.sessionManager?.getEntries?.() ?? [];
123
+ if (!Array.isArray(entries)) return false;
124
+ return entries.some((entry) => {
125
+ if (!entry || typeof entry !== "object") return false;
126
+ const record = entry;
127
+ if (
128
+ typeof record.type === "string" &&
129
+ ["message", "custom_message", "compaction", "branch_summary"].includes(record.type)
130
+ ) {
131
+ return true;
132
+ }
133
+ return (
134
+ record.type === "custom" &&
135
+ (record.customType === COGNITIVE_ROUTING_INTENT_ENTRY || record.customType === COGNITIVE_ROUTING_CONTROL_ENTRY)
136
+ );
137
+ });
138
+ } catch {
139
+ return false;
140
+ }
141
+ }
142
+ function hasCognitiveRoutingHost(pi, ctx) {
143
+ return (
144
+ isPiFlowHost(pi?.host) &&
145
+ typeof pi?.appendEntryDurable === "function" &&
146
+ typeof pi?.acquireModelStateControl === "function" &&
147
+ typeof ctx?.modelRegistry?.getApiKeyAndHeaders === "function"
148
+ );
149
+ }
150
+ async function reconcileCognitiveRoutingController(pi, ctx, capabilityState, previous) {
151
+ const cognitiveRouting = capabilityState?.cognitiveRouting;
152
+ if (
153
+ !isPiFlowHost(pi?.host) ||
154
+ !cognitiveRouting?.effective ||
155
+ startupSelectionSuppressesCognitiveRouting(ctx) ||
156
+ !hasCognitiveRoutingHost(pi, ctx)
157
+ ) {
158
+ if (previous) await previous.deactivate();
159
+ return undefined;
160
+ }
161
+ const controller = new CognitiveRoutingController({ capabilityState: cognitiveRouting, pi, ctx });
162
+ const recovered = await controller.recover();
163
+ if (recovered.status === "pending") return controller;
164
+ if (recovered.status !== "active") {
165
+ const activated = await controller.activate();
166
+ return activated.status === "active" ? controller : undefined;
167
+ }
168
+ return controller;
169
+ }
170
+ async function applyCapabilityToolVisibility(
171
+ pi,
172
+ ctx,
173
+ capabilityState = undefined,
174
+ cognitiveRoutingController = undefined,
175
+ ) {
29
176
  if (typeof pi?.setActiveTools !== "function" || typeof pi?.getAllTools !== "function") {
30
177
  return;
31
178
  }
32
- const state = capabilityState ?? (await readCapabilityState(ctx.cwd));
179
+ const state = capabilityState ?? (await readCapabilityState(ctx.cwd, ctx, pi?.host));
33
180
  const allToolNames = pi
34
181
  .getAllTools()
35
182
  .map((tool) => tool?.name)
@@ -39,22 +186,41 @@ async function applyCapabilityToolVisibility(pi, ctx, capabilityState = undefine
39
186
  const active = new Set(
40
187
  (Array.isArray(currentActive) ? currentActive : allToolNames).filter((name) => allToolNameSet.has(name)),
41
188
  );
42
- if (allToolNameSet.has(FREEFLOW_STATUS_TOOL_NAME)) {
43
- if (state.configured && state.enabled) active.add(FREEFLOW_STATUS_TOOL_NAME);
44
- else active.delete(FREEFLOW_STATUS_TOOL_NAME);
189
+ if (allToolNameSet.has(COGNITIVE_ROUTING_SWITCH_TOOL_NAME)) {
190
+ const controllerState = cognitiveRoutingController?.state();
191
+ const routingToolActive =
192
+ state.cognitiveRouting?.effective === true &&
193
+ controllerState?.effective === true &&
194
+ controllerState.controlMode === "automatic" &&
195
+ !startupSelectionSuppressesCognitiveRouting(ctx);
196
+ if (routingToolActive) active.add(COGNITIVE_ROUTING_SWITCH_TOOL_NAME);
197
+ else active.delete(COGNITIVE_ROUTING_SWITCH_TOOL_NAME);
45
198
  }
46
- for (const toolName of OUTPUT_ROUTER_TOOL_NAMES) {
47
- if (!allToolNameSet.has(toolName)) continue;
48
- if (state.outputRouter.enabled) active.add(toolName);
49
- else active.delete(toolName);
199
+ if (allToolNameSet.has(CONTEXT_VIRTUALIZATION_TOOL_NAME)) {
200
+ if (state.contextVirtualization?.effective === true || state.conversationHistory?.effective === true) {
201
+ active.add(CONTEXT_VIRTUALIZATION_TOOL_NAME);
202
+ } else {
203
+ active.delete(CONTEXT_VIRTUALIZATION_TOOL_NAME);
204
+ }
50
205
  }
51
206
  pi.setActiveTools([...active]);
52
207
  }
53
- async function applyLiveCapabilityState(pi, ctx) {
54
- const [modeState, capabilityState] = await Promise.all([readModeState(ctx.cwd), readCapabilityState(ctx.cwd)]);
208
+ async function applyLiveCapabilityState(pi, ctx, cognitiveRoutingController, options = {}) {
209
+ const [modeState, capabilityState] = await Promise.all([
210
+ readModeState(ctx.cwd),
211
+ readCapabilityState(ctx.cwd, ctx, pi?.host),
212
+ ]);
55
213
  await refreshRuntimeContext(capabilityState);
56
- setModeStatus(ctx, modeState, capabilityState);
57
- await applyCapabilityToolVisibility(pi, ctx, capabilityState);
214
+ let nextController = cognitiveRoutingController;
215
+ if (
216
+ options.reconcileCognitiveRouting &&
217
+ (nextController === undefined || capabilityState.cognitiveRouting?.effective !== true)
218
+ ) {
219
+ nextController = await reconcileCognitiveRoutingController(pi, ctx, capabilityState, nextController);
220
+ }
221
+ setModeStatus(ctx, modeState, capabilityState, nextController?.state());
222
+ await applyCapabilityToolVisibility(pi, ctx, capabilityState, nextController);
223
+ return nextController;
58
224
  }
59
225
  function disabledToolCall(toolName, capability) {
60
226
  const command = capability === "freeflow" ? "/freeflow settings" : `/${capability} settings`;
@@ -63,16 +229,7 @@ function disabledToolCall(toolName, capability) {
63
229
  reason: `${toolName} is disabled by Freeflow config. Configure ${capability} with ${command}.`,
64
230
  };
65
231
  }
66
- function capabilityCompletions(prefix) {
67
- const query = prefix ?? "";
68
- return [
69
- { value: "settings", label: "settings", description: "Open repository Output Router settings" },
70
- { value: "status", label: "status", description: "Show effective Output Router state" },
71
- { value: "enable", label: "enable", description: "Enable Output Router for this repository" },
72
- { value: "disable", label: "disable", description: "Disable Output Router for this repository" },
73
- ].filter((item) => item.value.startsWith(query));
74
- }
75
- function freeflowCompletions(prefix) {
232
+ function freeflowCompletions(prefix, hostInfo = undefined) {
76
233
  const query = prefix ?? "";
77
234
  if (query.startsWith("settings ")) {
78
235
  const settingsQuery = query.slice("settings ".length);
@@ -84,6 +241,12 @@ function freeflowCompletions(prefix) {
84
241
  .filter((item) => item.value.startsWith(settingsQuery))
85
242
  .map((item) => ({ ...item, value: `settings ${item.value}` }));
86
243
  }
244
+ if (isPiFlowHost(hostInfo) && query.startsWith("profile ")) {
245
+ return cognitiveRoutingProfileCompletions(query.slice("profile ".length)).map((item) => ({
246
+ ...item,
247
+ value: `profile ${item.value}`,
248
+ }));
249
+ }
87
250
  if (query.startsWith("mode ")) {
88
251
  const modeQuery = query.slice("mode ".length);
89
252
  return [
@@ -99,10 +262,25 @@ function freeflowCompletions(prefix) {
99
262
  .filter((item) => item.value.startsWith(modeQuery))
100
263
  .map((item) => ({ ...item, value: `mode ${item.value}` }));
101
264
  }
265
+ if (query.startsWith("context ")) {
266
+ const contextQuery = query.slice("context ".length);
267
+ return [
268
+ { value: "status", label: "status", description: "Show Freeflow Context state" },
269
+ { value: "list", label: "list", description: "List archived context projections" },
270
+ { value: "restore", label: "restore", description: "Restore one or more context references" },
271
+ { value: "reset all", label: "reset all", description: "Reset projection decisions on the active branch" },
272
+ ]
273
+ .filter((item) => item.value.startsWith(contextQuery))
274
+ .map((item) => ({ ...item, value: `context ${item.value}` }));
275
+ }
102
276
  return [
103
277
  { value: "settings", label: "settings", description: "Open personal override settings" },
104
278
  { value: "status", label: "status", description: "Show effective Freeflow state" },
279
+ { value: "context", label: "context", description: "Inspect Freeflow Context" },
105
280
  { value: "mode", label: "mode", description: "Select a temporary session mode" },
281
+ ...(isPiFlowHost(hostInfo)
282
+ ? [{ value: "profile", label: "profile", description: "Hold or release Cognitive Routing profile control" }]
283
+ : []),
106
284
  { value: "enable", label: "enable", description: "Enable Freeflow for this repository" },
107
285
  { value: "disable", label: "disable", description: "Disable Freeflow for this repository" },
108
286
  ].filter((item) => item.value.startsWith(query));
@@ -115,7 +293,7 @@ function bypassCompletions(prefix) {
115
293
  ].filter((item) => item.value.startsWith(query));
116
294
  }
117
295
  async function sendSkillCommand(pi, ctx, skill, args) {
118
- const state = await readCapabilityState(ctx.cwd);
296
+ const state = await readCapabilityState(ctx.cwd, ctx, pi?.host);
119
297
  if (skill === "setup-freeflow" && !state.configured) {
120
298
  await pi.sendUserMessage(skillPrompt(skill, args));
121
299
  return;
@@ -138,93 +316,307 @@ async function sendSkillCommand(pi, ctx, skill, args) {
138
316
  await pi.sendUserMessage(skillPrompt(skill, args));
139
317
  }
140
318
  export default function freeflow(pi) {
141
- registerRouterTools(pi);
319
+ let cognitiveRoutingController;
320
+ let latestCognitiveRoutingContext;
321
+ let providerSurfaceSnapshot;
322
+ let freeflowContextRuntime;
323
+ let contextVirtualizationRuntime;
324
+ let conversationHistoryRuntime;
325
+ const registerContextToolForState = (capabilityState) => {
326
+ registerFreeflowContextTool(
327
+ pi,
328
+ () => contextVirtualizationRuntime,
329
+ () => conversationHistoryRuntime,
330
+ {
331
+ contextVirtualization: capabilityState?.contextVirtualization?.effective === true,
332
+ conversationHistory: capabilityState?.conversationHistory?.effective === true,
333
+ },
334
+ );
335
+ };
336
+ const buildProviderSurface = async (ctx, activateCognitiveRouting = false) => {
337
+ const [modeState, capabilityState] = await Promise.all([
338
+ readModeState(ctx.cwd),
339
+ readCapabilityState(ctx.cwd, ctx, pi?.host),
340
+ ]);
341
+ const freeflowContext = await getRuntimeContext(capabilityState);
342
+ const promptCapabilityState = modelFacingCapabilityState(
343
+ capabilityState,
344
+ ctx,
345
+ freeflowContext,
346
+ cognitiveRoutingController,
347
+ );
348
+ let activationAttempted = false;
349
+ if (
350
+ activateCognitiveRouting &&
351
+ (cognitiveRoutingController === undefined || promptCapabilityState.cognitiveRouting?.effective !== true)
352
+ ) {
353
+ activationAttempted =
354
+ promptCapabilityState.cognitiveRouting?.effective === true && !startupSelectionSuppressesCognitiveRouting(ctx);
355
+ try {
356
+ cognitiveRoutingController = await reconcileCognitiveRoutingController(
357
+ pi,
358
+ ctx,
359
+ promptCapabilityState,
360
+ cognitiveRoutingController,
361
+ );
362
+ } catch {
363
+ cognitiveRoutingController = undefined;
364
+ }
365
+ }
366
+ const surfaceCapabilityState = modelFacingCapabilityState(
367
+ promptCapabilityState,
368
+ ctx,
369
+ freeflowContext,
370
+ cognitiveRoutingController,
371
+ activationAttempted && !cognitiveRoutingController,
372
+ );
373
+ return {
374
+ modeState: modelFacingModeState(modeState, surfaceCapabilityState),
375
+ capabilityState: surfaceCapabilityState,
376
+ freeflowContext,
377
+ cognitiveRoutingRuntime: cognitiveRoutingController?.state(),
378
+ configuredCapabilityState: capabilityState,
379
+ };
380
+ };
381
+ const applyLiveCapabilityStateForSession = async (ctx, options = {}) => {
382
+ cognitiveRoutingController = await applyLiveCapabilityState(pi, ctx, cognitiveRoutingController, options);
383
+ registerContextToolForState(await readCapabilityState(ctx.cwd, ctx, pi?.host));
384
+ };
385
+ if (isPiFlowHost(pi?.host)) {
386
+ registerCognitiveRoutingTool(pi, () => cognitiveRoutingController);
387
+ registerCognitiveRoutingHistoryTool(pi, (options, context) => {
388
+ if (cognitiveRoutingController) return cognitiveRoutingController.history(options);
389
+ return readCognitiveRoutingHistory(context ?? latestCognitiveRoutingContext, options);
390
+ });
391
+ }
392
+ registerFreeflowContextTool(
393
+ pi,
394
+ () => contextVirtualizationRuntime,
395
+ () => conversationHistoryRuntime,
396
+ { contextVirtualization: false, conversationHistory: false },
397
+ );
398
+ if (isPiFlowHost(pi?.host) && typeof pi.registerShortcut === "function") {
399
+ pi.registerShortcut("ctrl+shift+r", {
400
+ description: "Cycle the Cognitive Routing manual standard/reasoning hold",
401
+ handler: async (ctx) => {
402
+ if (typeof ctx?.isIdle === "function" && !ctx.isIdle()) {
403
+ ctx.ui?.notify?.("Freeflow settings and profile changes are available only while Pi is idle.", "warning");
404
+ return;
405
+ }
406
+ if (!cognitiveRoutingController) {
407
+ await applyLiveCapabilityStateForSession(ctx, { reconcileCognitiveRouting: true });
408
+ }
409
+ const controller = cognitiveRoutingController;
410
+ if (!controller) {
411
+ ctx.ui?.notify?.("Cognitive Routing is unavailable for this session.", "warning");
412
+ return;
413
+ }
414
+ const current = controller.state().activeProfile;
415
+ const target = current === "reasoning" ? "standard" : "reasoning";
416
+ const result = await controller.setManualProfile(target, "profile-shortcut");
417
+ if (result.status === "active") {
418
+ ctx.ui?.notify?.(`Cognitive Routing manual hold set to ${target}.`, "info");
419
+ } else {
420
+ ctx.ui?.notify?.(`Cognitive Routing could not set the manual profile: ${result.reason}.`, "warning");
421
+ }
422
+ await applyLiveCapabilityStateForSession(ctx);
423
+ },
424
+ });
425
+ pi.registerShortcut("ctrl+shift+a", {
426
+ description: "Cycle the Cognitive Routing automatic standard/reasoning profile",
427
+ handler: async (ctx) => {
428
+ if (typeof ctx?.isIdle === "function" && !ctx.isIdle()) {
429
+ ctx.ui?.notify?.("Freeflow settings and profile changes are available only while Pi is idle.", "warning");
430
+ return;
431
+ }
432
+ if (!cognitiveRoutingController) {
433
+ await applyLiveCapabilityStateForSession(ctx, { reconcileCognitiveRouting: true });
434
+ }
435
+ const controller = cognitiveRoutingController;
436
+ if (!controller) {
437
+ ctx.ui?.notify?.("Cognitive Routing is unavailable for this session.", "warning");
438
+ return;
439
+ }
440
+ const state = controller.state();
441
+ const target = state.activeProfile === "reasoning" ? "standard" : "reasoning";
442
+ const result =
443
+ state.controlMode === "automatic" && state.activeProfile
444
+ ? await controller.switchAutomaticProfile(
445
+ target,
446
+ `Cycle automatic profile to ${target}.`,
447
+ "user",
448
+ "profile-shortcut",
449
+ )
450
+ : await controller.setAutomaticControl("profile-shortcut");
451
+ if (result.status === "automatic") {
452
+ ctx.ui?.notify?.("Cognitive Routing automatic control active.", "info");
453
+ } else if (result.status === "active") {
454
+ ctx.ui?.notify?.(`Cognitive Routing automatic profile set to ${result.profile}.`, "info");
455
+ } else {
456
+ ctx.ui?.notify?.(`Cognitive Routing could not cycle the automatic profile: ${result.reason}.`, "warning");
457
+ }
458
+ await applyLiveCapabilityStateForSession(ctx);
459
+ },
460
+ });
461
+ }
142
462
  pi.on("resources_discover", async (event, ctx) => {
143
463
  const cwd = ctx?.cwd ?? event?.cwd ?? process.cwd();
144
- const state = await readCapabilityState(cwd);
464
+ const snapshot =
465
+ providerSurfaceSnapshot?.context === ctx
466
+ ? providerSurfaceSnapshot.value
467
+ : await buildProviderSurface(ctx ?? { cwd }, false);
468
+ const state = snapshot.capabilityState;
145
469
  if (!state.configured) {
146
470
  return { skillPaths: [freeflowSkillPath("setup-freeflow")] };
147
471
  }
148
472
  if (!state.enabled || !state.skills.effective) {
149
473
  return { skillPaths: [] };
150
474
  }
151
- return { skillPaths: freeflowModelSkillPaths() };
475
+ return { skillPaths: freeflowModelSkillPaths(state) };
152
476
  });
153
477
  pi.on("session_start", async (_event, ctx) => {
478
+ latestCognitiveRoutingContext = ctx;
479
+ providerSurfaceSnapshot = undefined;
154
480
  restoreModeOverride(ctx);
155
- const [modeState, routerConfigResult, capabilityState] = await Promise.all([
156
- readModeState(ctx.cwd),
157
- readOutputRouterConfig(ctx.cwd),
158
- readCapabilityState(ctx.cwd),
159
- ]);
481
+ freeflowContextRuntime = new FreeflowContextRuntime(ctx);
482
+ contextVirtualizationRuntime = new ContextVirtualizationRuntime(pi, ctx, freeflowContextRuntime);
483
+ conversationHistoryRuntime = new ConversationHistoryRuntime(
484
+ ctx,
485
+ (entryId) => contextVirtualizationRuntime?.isSourceFullyProjected(entryId) ?? true,
486
+ freeflowContextRuntime,
487
+ );
488
+ await contextVirtualizationRuntime.recover(ctx);
489
+ const capabilityState = await readCapabilityState(ctx.cwd, ctx, pi?.host);
160
490
  await refreshRuntimeContext(capabilityState);
161
- setModeStatus(ctx, modeState, capabilityState);
162
- notifyRouterConfigWarnings(ctx, routerConfigResult);
163
- await applyCapabilityToolVisibility(pi, ctx, capabilityState);
491
+ const hasSessionState = sessionHasConversationOrRoutingState(ctx);
492
+ const snapshot = await buildProviderSurface(ctx, hasSessionState);
493
+ const cognitiveRoutingStartupPending =
494
+ snapshot.capabilityState?.cognitiveRouting?.effective === true &&
495
+ !hasSessionState &&
496
+ !startupSelectionSuppressesCognitiveRouting(ctx);
497
+ registerContextToolForState(snapshot.capabilityState);
498
+ setModeStatus(ctx, snapshot.modeState, snapshot.capabilityState, snapshot.cognitiveRoutingRuntime, {
499
+ cognitiveRoutingStartupPending,
500
+ });
501
+ await applyCapabilityToolVisibility(pi, ctx, snapshot.capabilityState, cognitiveRoutingController);
502
+ });
503
+ pi.on("agent_settled", async (_event, ctx) => {
504
+ if (!cognitiveRoutingController) return undefined;
505
+ await applyLiveCapabilityStateForSession(ctx);
506
+ return undefined;
507
+ });
508
+ pi.on("session_shutdown", async (event) => {
509
+ providerSurfaceSnapshot = undefined;
510
+ const controller = cognitiveRoutingController;
511
+ cognitiveRoutingController = undefined;
512
+ freeflowContextRuntime = undefined;
513
+ contextVirtualizationRuntime = undefined;
514
+ conversationHistoryRuntime = undefined;
515
+ if (controller) await controller.shutdown(event?.reason);
164
516
  });
165
517
  pi.on("session_tree", async (_event, ctx) => {
518
+ latestCognitiveRoutingContext = ctx;
519
+ providerSurfaceSnapshot = undefined;
166
520
  restoreModeOverride(ctx);
167
- await applyLiveCapabilityState(pi, ctx);
521
+ const controller = cognitiveRoutingController;
522
+ if (controller) await controller.reconcileBranch();
523
+ if (contextVirtualizationRuntime) {
524
+ contextVirtualizationRuntime.setContext(ctx);
525
+ await contextVirtualizationRuntime.recover(ctx);
526
+ }
527
+ conversationHistoryRuntime?.setContext(ctx);
528
+ await applyLiveCapabilityStateForSession(ctx);
168
529
  });
169
530
  pi.on("session_compact", async (_event, ctx) => {
170
- const [modeState, routerConfigResult, capabilityState] = await Promise.all([
531
+ latestCognitiveRoutingContext = ctx;
532
+ providerSurfaceSnapshot = undefined;
533
+ const controller = cognitiveRoutingController;
534
+ if (controller) await controller.reconcileBranch("session-compact");
535
+ if (contextVirtualizationRuntime) {
536
+ contextVirtualizationRuntime.setContext(ctx);
537
+ await contextVirtualizationRuntime.recover(ctx);
538
+ }
539
+ conversationHistoryRuntime?.setContext(ctx);
540
+ const [modeState, capabilityState] = await Promise.all([
171
541
  readModeState(ctx.cwd),
172
- readOutputRouterConfig(ctx.cwd),
173
- readCapabilityState(ctx.cwd),
542
+ readCapabilityState(ctx.cwd, ctx, pi?.host),
174
543
  ]);
175
544
  await refreshRuntimeContext(capabilityState);
176
- setModeStatus(ctx, modeState, capabilityState);
177
- notifyRouterConfigWarnings(ctx, routerConfigResult);
178
- await applyCapabilityToolVisibility(pi, ctx, capabilityState);
545
+ registerContextToolForState(capabilityState);
546
+ setModeStatus(ctx, modeState, capabilityState, cognitiveRoutingController?.state());
547
+ await applyCapabilityToolVisibility(pi, ctx, capabilityState, cognitiveRoutingController);
179
548
  });
180
549
  pi.on("before_agent_start", async (event, ctx) => {
181
- const [modeState, routerConfigResult, capabilityState] = await Promise.all([
182
- readModeState(ctx.cwd),
183
- readOutputRouterConfig(ctx.cwd),
184
- readCapabilityState(ctx.cwd),
185
- ]);
186
- const freeflowContext = await getRuntimeContext(capabilityState);
187
- setModeStatus(ctx, modeState, capabilityState);
188
- notifyRouterConfigWarnings(ctx, routerConfigResult);
189
- await applyCapabilityToolVisibility(pi, ctx, capabilityState);
190
- const freeflowRuntimeContext = runtimeContext(modeState, freeflowContext, routerConfigResult, capabilityState);
191
- const workflowMessage = workflowBootstrapMessage(freeflowContext, capabilityState, ctx.sessionManager);
550
+ latestCognitiveRoutingContext = ctx;
551
+ const snapshot = await buildProviderSurface(ctx, true);
552
+ providerSurfaceSnapshot = { context: ctx, value: snapshot };
553
+ registerContextToolForState(snapshot.capabilityState);
554
+ setModeStatus(ctx, snapshot.modeState, snapshot.capabilityState, snapshot.cognitiveRoutingRuntime);
555
+ await applyCapabilityToolVisibility(pi, ctx, snapshot.capabilityState, cognitiveRoutingController);
556
+ const freeflowRuntimeContext = runtimeContext(snapshot.freeflowContext, snapshot.capabilityState);
192
557
  const systemPrompt = freeflowRuntimeContext
193
558
  ? `${event.systemPrompt}\n\n${freeflowRuntimeContext}`
194
559
  : event.systemPrompt;
195
- return { message: workflowMessage, systemPrompt };
560
+ return { systemPrompt };
196
561
  });
197
562
  pi.on("context", async (event, ctx) => {
198
- const capabilityState = await readCapabilityState(ctx.cwd);
199
- if (capabilityState.skills.effective) {
200
- return undefined;
563
+ const snapshot =
564
+ providerSurfaceSnapshot?.context === ctx ? providerSurfaceSnapshot.value : await buildProviderSurface(ctx, false);
565
+ if (providerSurfaceSnapshot?.context === ctx) providerSurfaceSnapshot = undefined;
566
+ const cognitiveRoutingRuntime = snapshot.cognitiveRoutingRuntime;
567
+ const surfaceCapabilityState = snapshot.capabilityState;
568
+ const surfaceModeState = snapshot.modeState;
569
+ let changed = false;
570
+ let messages = event.messages
571
+ .map((message) => {
572
+ const filtered = filterBootstrapMessage(message);
573
+ if (filtered !== message) changed = true;
574
+ return filtered;
575
+ })
576
+ .filter((message) => message !== undefined);
577
+ if (contextVirtualizationRuntime) {
578
+ contextVirtualizationRuntime.setContext(ctx);
579
+ const projected = await contextVirtualizationRuntime.project(
580
+ messages,
581
+ surfaceCapabilityState.contextVirtualization?.effective === true,
582
+ );
583
+ if (projected.changed) {
584
+ changed = true;
585
+ messages = projected.messages;
586
+ }
587
+ }
588
+ if (conversationHistoryRuntime && surfaceCapabilityState.conversationHistory?.effective === true) {
589
+ conversationHistoryRuntime.setContext(ctx);
590
+ conversationHistoryRuntime.capture(surfaceCapabilityState.contextVirtualization?.effective === true);
201
591
  }
202
- const messages = event.messages.filter(
203
- (message) => !(message?.role === "custom" && message?.customType === WORKFLOW_BOOTSTRAP_MESSAGE_TYPE),
592
+ const nextMessages = withFreeflowRuntimeState(
593
+ messages,
594
+ surfaceModeState,
595
+ surfaceCapabilityState,
596
+ cognitiveRoutingRuntime,
204
597
  );
205
- return messages.length === event.messages.length ? undefined : { messages };
598
+ changed = true;
599
+ messages = nextMessages;
600
+ return changed ? { messages } : undefined;
206
601
  });
207
602
  pi.on("tool_call", async (event, ctx) => {
208
- const capabilityState = await readCapabilityState(ctx.cwd);
603
+ const capabilityState = await readCapabilityState(ctx.cwd, ctx, pi?.host);
209
604
  const toolName = typeof event?.toolName === "string" ? event.toolName : "";
210
- if ((!capabilityState.configured || !capabilityState.enabled) && toolName === FREEFLOW_STATUS_TOOL_NAME) {
211
- return disabledToolCall(toolName, "freeflow");
212
- }
213
- if (!capabilityState.outputRouter.enabled && isOutputRouterToolName(toolName)) {
214
- return disabledToolCall(toolName, "output-router");
605
+ if (
606
+ capabilityState.contextVirtualization?.effective !== true &&
607
+ capabilityState.conversationHistory?.effective !== true &&
608
+ toolName === CONTEXT_VIRTUALIZATION_TOOL_NAME
609
+ ) {
610
+ return disabledToolCall(toolName, "context");
215
611
  }
216
612
  return undefined;
217
613
  });
218
614
  pi.on("tool_result", async (event, ctx) => {
219
- const capabilityState = await readCapabilityState(ctx.cwd);
220
- if (!capabilityState.outputRouter.enabled) {
221
- return undefined;
222
- }
223
- const observed = await handleObservedToolRouting(event, ctx);
224
- if (observed) {
225
- return observed;
615
+ const toolName = typeof event?.toolName === "string" ? event.toolName : "";
616
+ if (isPiFlowHost(pi?.host) && toolName === COGNITIVE_ROUTING_SWITCH_TOOL_NAME) {
617
+ await applyLiveCapabilityStateForSession(ctx);
226
618
  }
227
- return handleNativeToolSafetyNet(event, ctx);
619
+ return undefined;
228
620
  });
229
621
  for (const { command, skill } of WORKFLOW_COMMANDS) {
230
622
  pi.registerCommand(command, {
@@ -245,25 +637,51 @@ export default function freeflow(pi) {
245
637
  }
246
638
  pi.registerCommand("freeflow", {
247
639
  description: "Open unified Freeflow settings or print compact status",
248
- getArgumentCompletions: freeflowCompletions,
640
+ getArgumentCompletions: (prefix) => freeflowCompletions(prefix, pi?.host),
249
641
  handler: async (args, ctx) => {
642
+ const contextInput = (args ?? "").trim();
643
+ if (contextInput === "context" || contextInput.startsWith("context ")) {
644
+ const capabilityState = await readCapabilityState(ctx.cwd, ctx, pi?.host);
645
+ await handleContextCommand(
646
+ contextInput.slice("context".length).trim(),
647
+ ctx,
648
+ contextVirtualizationRuntime,
649
+ capabilityState.contextVirtualization?.effective === true,
650
+ capabilityState.conversationHistory?.effective === true,
651
+ );
652
+ return;
653
+ }
654
+ if (isPiFlowHost(pi?.host) && /^profile(?:\s|$)/i.test((args ?? "").trim())) {
655
+ const profileCommandContext = {
656
+ isIdle: ctx?.isIdle,
657
+ ui: ctx?.ui,
658
+ history: (options) =>
659
+ cognitiveRoutingController?.history(options) ?? readCognitiveRoutingHistory(ctx, options),
660
+ };
661
+ const historyCommand = /^profile\s+history(?:\s|$)/i.test((args ?? "").trim());
662
+ if (historyCommand) {
663
+ await handleCognitiveRoutingProfileCommand(args, profileCommandContext, cognitiveRoutingController);
664
+ return;
665
+ }
666
+ if (!cognitiveRoutingController) {
667
+ await applyLiveCapabilityStateForSession(ctx, { reconcileCognitiveRouting: true });
668
+ }
669
+ if (await handleCognitiveRoutingProfileCommand(args, profileCommandContext, cognitiveRoutingController)) {
670
+ await applyLiveCapabilityStateForSession(ctx);
671
+ return;
672
+ }
673
+ }
250
674
  await handleFreeflowCommand(
251
675
  args,
252
676
  ctx,
253
- async () => {
254
- await applyLiveCapabilityState(pi, ctx);
677
+ async (_changed, options = {}) => {
678
+ await applyLiveCapabilityStateForSession(ctx, {
679
+ reconcileCognitiveRouting: options.reconcileCognitiveRouting ?? true,
680
+ });
255
681
  },
256
682
  pi,
683
+ cognitiveRoutingController,
257
684
  );
258
685
  },
259
686
  });
260
- pi.registerCommand("output-router", {
261
- description: "Open Freeflow Output Router settings or print compact status",
262
- getArgumentCompletions: capabilityCompletions,
263
- handler: async (args, ctx) => {
264
- await handleOutputRouterCommand(args, ctx, async () => {
265
- await applyLiveCapabilityState(pi, ctx);
266
- });
267
- },
268
- });
269
687
  }