@hassangameryt/freeflow 0.6.0 → 0.7.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.
- package/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +2 -2
- package/.codex-plugin/plugin.json +4 -5
- package/README.md +39 -55
- package/capabilities/cognitive-routing/SKILL.md +288 -130
- package/command-surface.json +0 -24
- package/hooks/freeflow-runtime-context.mjs +42 -477
- package/hooks/hooks.json +1 -26
- package/hooks/tests/check-runtime-context-hook.sh +108 -319
- package/package.json +4 -2
- package/pi-extension/dist/cognitive-routing/commands.js +3 -3
- package/pi-extension/dist/cognitive-routing/config.js +16 -20
- package/pi-extension/dist/cognitive-routing/controller.js +478 -48
- package/pi-extension/dist/cognitive-routing/history.js +12 -0
- package/pi-extension/dist/cognitive-routing/host.js +74 -12
- package/pi-extension/dist/cognitive-routing/pi-routing-session.js +414 -0
- package/pi-extension/dist/cognitive-routing/pi-session-control.js +320 -0
- package/pi-extension/dist/cognitive-routing/tool.js +1 -0
- package/pi-extension/dist/cognitive-routing/types.js +1 -1
- package/pi-extension/dist/index.js +236 -219
- package/pi-extension/dist/runtime/runtime-context.js +126 -286
- package/pi-extension/dist/settings/settings-ui.js +52 -336
- package/pi-extension/src/cognitive-routing/commands.ts +15 -5
- package/pi-extension/src/cognitive-routing/config.ts +16 -20
- package/pi-extension/src/cognitive-routing/controller.ts +561 -51
- package/pi-extension/src/cognitive-routing/history.ts +12 -0
- package/pi-extension/src/cognitive-routing/host.ts +110 -16
- package/pi-extension/src/cognitive-routing/pi-routing-session.ts +538 -0
- package/pi-extension/src/cognitive-routing/pi-session-control.ts +444 -0
- package/pi-extension/src/cognitive-routing/tool.ts +1 -0
- package/pi-extension/src/cognitive-routing/types.ts +1 -1
- package/pi-extension/src/index.ts +249 -239
- package/pi-extension/src/runtime/runtime-context.ts +129 -305
- package/pi-extension/src/settings/settings-ui.ts +53 -371
- package/pi-extension/tests/cognitive-routing/commands.test.js +1 -1
- package/pi-extension/tests/cognitive-routing/controller.test.js +69 -40
- package/pi-extension/tests/cognitive-routing/extension-lifecycle.test.js +128 -57
- package/pi-extension/tests/cognitive-routing/pi-normal-lifecycle.test.js +434 -0
- package/pi-extension/tests/cognitive-routing/pi-session-control.test.js +174 -0
- package/pi-extension/tests/cognitive-routing/pi-session-history.test.js +91 -0
- package/pi-extension/tests/cognitive-routing/profile-resolution.test.js +47 -4
- package/pi-extension/tests/integration/mode-free-core.test.js +218 -0
- package/pi-extension/tests/integration/pi-extension.test.js +430 -2478
- package/pi-extension/tests/integration/prompt-architecture.test.js +124 -79
- package/pi-extension/tests/integration/unaffected-regressions.test.js +411 -0
- package/runtime/prompts/cognitive-routing.md +5 -4
- package/runtime/prompts/conversation-history.md +1 -1
- package/runtime/prompts/core.md +77 -6
- package/runtime/prompts/interaction-contract.md +6 -2
- package/skills/action-selection/SKILL.md +93 -44
- package/skills/action-selection/references/trajectory-stalls.md +71 -0
- package/skills/bypass/SKILL.md +109 -39
- package/skills/commit-work/SKILL.md +94 -55
- package/skills/commit-work/references/git-state-edges.md +94 -0
- package/skills/commit-work/references/simple-push.md +92 -0
- package/skills/commit-work/references/staging-decisions.md +79 -46
- package/skills/decision-gate/SKILL.md +80 -22
- package/skills/design-for-depth/SKILL.md +208 -43
- package/skills/design-for-depth/references/design-pressure-signals.md +108 -240
- package/skills/design-for-depth/references/interface-design-loop.md +77 -97
- package/skills/design-for-depth/references/module-and-dependency-design.md +147 -0
- package/skills/design-for-depth/references/software-design-philosophy.md +127 -173
- package/skills/design-for-depth/references/state-and-failure-boundaries.md +136 -0
- package/skills/diagnose-failure/SKILL.md +198 -52
- package/skills/diagnose-failure/references/diagnostic-loop-catalog.md +19 -5
- package/skills/diagnose-failure/references/flaky-and-performance-diagnosis.md +13 -5
- package/skills/discuss/SKILL.md +118 -76
- package/skills/discuss/references/discussion-continuity.md +84 -32
- package/skills/evaluate-skill/SKILL.md +166 -52
- package/skills/evaluate-skill/references/evaluation-definition-schema.md +2 -2
- package/skills/evaluate-skill/references/evaluation-design.md +56 -30
- package/skills/evaluate-skill/references/execution-and-evidence.md +1 -1
- package/skills/evaluate-skill/references/review-and-revision.md +62 -21
- package/skills/execute-work/SKILL.md +98 -59
- package/skills/execute-work/references/code-practices.md +4 -4
- package/skills/execute-work/references/execute-work-edges.md +42 -22
- package/skills/review-artifact/SKILL.md +132 -71
- package/skills/review-artifact/references/adjudicate-artifact-review.md +101 -0
- package/skills/review-artifact/references/independent-artifact-reviewer-contract.md +52 -41
- package/skills/review-work/SKILL.md +115 -72
- package/skills/review-work/references/adjudicate-work-review.md +97 -0
- package/skills/review-work/references/independent-work-reviewer-contract.md +40 -35
- package/skills/review-work/references/security-risk-lens.md +17 -15
- package/skills/setup-freeflow/SKILL.md +14 -17
- package/skills/setup-freeflow/references/activation-contract.md +24 -30
- package/skills/setup-freeflow/references/host-setup.md +6 -7
- package/skills/simplify-code/SKILL.md +97 -39
- package/skills/simplify-code/references/simplification-patterns.md +1 -1
- package/skills/tdd/SKILL.md +108 -41
- package/skills/tdd/references/test-design.md +1 -1
- package/skills/track-work/SKILL.md +133 -300
- package/skills/track-work/references/working-record-format.md +515 -0
- package/skills/track-work/scripts/lib/document.mjs +713 -0
- package/skills/track-work/scripts/lib/format.mjs +166 -0
- package/skills/track-work/scripts/lib/store.mjs +233 -0
- package/skills/track-work/scripts/lib/transitions.mjs +790 -0
- package/skills/track-work/scripts/lib/views.mjs +27 -430
- package/skills/track-work/scripts/working-record.mjs +292 -98
- package/skills/verify-work/SKILL.md +46 -20
- package/skills/verify-work/references/browser-runtime-evidence.md +1 -1
- package/skills/verify-work/references/integration-evidence.md +1 -7
- package/skills/verify-work/references/performance-evidence.md +1 -1
- package/skills/workflow/SKILL.md +110 -80
- package/skills/workflow/references/domain-skill-composition.md +24 -18
- package/skills/write-skill/SKILL.md +218 -62
- package/skills/write-skill/references/activation-boundaries.md +63 -21
- package/skills/write-skill/references/agent-first-instructions.md +61 -27
- package/skills/write-skill/references/progressive-disclosure.md +91 -41
- package/skills/write-skill/references/skill-dependency-graphs.md +190 -0
- package/runtime/prompts/skills.md +0 -65
- package/skills/mode-contract/SKILL.md +0 -104
- package/skills/track-work/scripts/lib/codec.mjs +0 -570
- package/skills/track-work/scripts/lib/commands.mjs +0 -568
- package/skills/track-work/scripts/lib/contract.mjs +0 -303
- package/skills/track-work/scripts/lib/model.mjs +0 -506
- package/skills/track-work/scripts/lib/operations.mjs +0 -965
- package/skills/track-work/scripts/lib/record-store.mjs +0 -264
- package/skills/track-work/scripts/lib/result.mjs +0 -37
- package/skills/track-work/scripts/lib/rewrites.mjs +0 -740
- package/skills/track-work/scripts/lib/schema.mjs +0 -277
- package/skills/track-work/scripts/lib/source-inventory.mjs +0 -162
- package/skills/track-work/scripts/lib/workspace.mjs +0 -134
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
COGNITIVE_ROUTING_CONTROL_ENTRY,
|
|
3
|
+
COGNITIVE_ROUTING_INACTIVE_ENTRY,
|
|
3
4
|
COGNITIVE_ROUTING_INTENT_ENTRY,
|
|
4
|
-
CognitiveRoutingController,
|
|
5
5
|
} from "./cognitive-routing/controller.js";
|
|
6
|
+
import { PiRoutingSession } from "./cognitive-routing/pi-routing-session.js";
|
|
6
7
|
import {
|
|
7
8
|
cognitiveRoutingProfileCompletions,
|
|
8
9
|
handleCognitiveRoutingProfileCommand,
|
|
@@ -23,19 +24,17 @@ import {
|
|
|
23
24
|
freeflowModelSkillPaths,
|
|
24
25
|
freeflowSkillPath,
|
|
25
26
|
getRuntimeContext,
|
|
27
|
+
hasUsableMandatoryPrompts,
|
|
28
|
+
isPromptAvailable,
|
|
26
29
|
readCapabilityState,
|
|
27
|
-
readModeState,
|
|
28
30
|
refreshRuntimeContext,
|
|
29
|
-
|
|
31
|
+
restoreSessionOverrides,
|
|
30
32
|
runtimeContext,
|
|
31
33
|
filterBootstrapMessage,
|
|
32
|
-
|
|
34
|
+
setFreeflowStatus,
|
|
33
35
|
skillPrompt,
|
|
34
36
|
withFreeflowRuntimeState,
|
|
35
37
|
} from "./runtime/runtime-context.js";
|
|
36
|
-
function startupSelectionSuppressesCognitiveRouting(ctx) {
|
|
37
|
-
return ctx?.modelStateProvenance?.explicitModel === true || ctx?.modelStateProvenance?.explicitThinking === true;
|
|
38
|
-
}
|
|
39
38
|
function unavailableCapability(capability, code, message) {
|
|
40
39
|
return {
|
|
41
40
|
...capability,
|
|
@@ -45,15 +44,12 @@ function unavailableCapability(capability, code, message) {
|
|
|
45
44
|
}
|
|
46
45
|
function modelFacingCapabilityState(
|
|
47
46
|
capabilityState,
|
|
48
|
-
ctx,
|
|
49
47
|
freeflowContext,
|
|
50
|
-
|
|
48
|
+
routingSnapshot,
|
|
51
49
|
cognitiveRoutingActivationFailed = false,
|
|
52
50
|
) {
|
|
53
51
|
const surfaceState = {
|
|
54
52
|
...capabilityState,
|
|
55
|
-
interactionContract: { ...capabilityState?.interactionContract },
|
|
56
|
-
skills: { ...capabilityState?.skills },
|
|
57
53
|
contextVirtualization: { ...capabilityState?.contextVirtualization },
|
|
58
54
|
conversationHistory: { ...capabilityState?.conversationHistory },
|
|
59
55
|
cognitiveRouting: { ...capabilityState?.cognitiveRouting },
|
|
@@ -64,59 +60,62 @@ function modelFacingCapabilityState(
|
|
|
64
60
|
surfaceState[key] = unavailableCapability(surfaceState[key], "unavailable", message);
|
|
65
61
|
}
|
|
66
62
|
};
|
|
67
|
-
if (!freeflowContext
|
|
68
|
-
for (const key of [
|
|
69
|
-
"
|
|
70
|
-
"skills",
|
|
71
|
-
"contextVirtualization",
|
|
72
|
-
"conversationHistory",
|
|
73
|
-
"cognitiveRouting",
|
|
74
|
-
]) {
|
|
75
|
-
markUnavailable(key, "Freeflow core prompt is unavailable.");
|
|
63
|
+
if (!hasUsableMandatoryPrompts(freeflowContext)) {
|
|
64
|
+
for (const key of ["contextVirtualization", "conversationHistory", "cognitiveRouting"]) {
|
|
65
|
+
markUnavailable(key, "Mandatory Freeflow prompt is unavailable.");
|
|
76
66
|
}
|
|
77
67
|
return surfaceState;
|
|
78
68
|
}
|
|
79
|
-
if (
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
markUnavailable("
|
|
69
|
+
if (
|
|
70
|
+
surfaceState.contextVirtualization?.effective === true &&
|
|
71
|
+
!isPromptAvailable(freeflowContext.contextVirtualizationPrompt)
|
|
72
|
+
) {
|
|
73
|
+
markUnavailable("contextVirtualization", "Context Virtualization prompt is unavailable.");
|
|
84
74
|
}
|
|
85
|
-
if (
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
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
|
-
}
|
|
75
|
+
if (
|
|
76
|
+
surfaceState.conversationHistory?.effective === true &&
|
|
77
|
+
!isPromptAvailable(freeflowContext.conversationHistoryPrompt)
|
|
78
|
+
) {
|
|
79
|
+
markUnavailable("conversationHistory", "Conversation History prompt is unavailable.");
|
|
96
80
|
}
|
|
97
81
|
if (surfaceState.cognitiveRouting?.effective === true) {
|
|
98
|
-
|
|
82
|
+
const controllerState = routingSnapshot.runtimeState;
|
|
83
|
+
if (routingSnapshot.disposition === "blocked") {
|
|
84
|
+
surfaceState.cognitiveRouting = unavailableCapability(
|
|
85
|
+
surfaceState.cognitiveRouting,
|
|
86
|
+
"runtime_blocked",
|
|
87
|
+
routingSnapshot.reason ?? "Cognitive Routing is blocked because its inactive state could not be persisted.",
|
|
88
|
+
);
|
|
89
|
+
} else if (routingSnapshot.startupSelectionSuppressed || routingSnapshot.disposition === "inactive") {
|
|
90
|
+
surfaceState.cognitiveRouting = unavailableCapability(
|
|
91
|
+
surfaceState.cognitiveRouting,
|
|
92
|
+
"runtime_inactive",
|
|
93
|
+
"Cognitive Routing is inactive because Pi owns the startup model or thinking level.",
|
|
94
|
+
);
|
|
95
|
+
} else if (controllerState?.runtimeStatus === "inactive") {
|
|
99
96
|
surfaceState.cognitiveRouting = unavailableCapability(
|
|
100
97
|
surfaceState.cognitiveRouting,
|
|
101
98
|
"runtime_inactive",
|
|
102
|
-
"Cognitive Routing is inactive because
|
|
99
|
+
controllerState.runtimeReason ?? "Cognitive Routing is inactive because Pi owns the current model state.",
|
|
100
|
+
);
|
|
101
|
+
} else if (controllerState?.runtimeStatus === "blocked") {
|
|
102
|
+
surfaceState.cognitiveRouting = unavailableCapability(
|
|
103
|
+
surfaceState.cognitiveRouting,
|
|
104
|
+
"runtime_blocked",
|
|
105
|
+
controllerState.runtimeReason ?? "Cognitive Routing is blocked because its state is not proven.",
|
|
103
106
|
);
|
|
104
|
-
} else if (cognitiveRoutingActivationFailed ||
|
|
107
|
+
} else if (cognitiveRoutingActivationFailed || controllerState?.effective === false) {
|
|
105
108
|
surfaceState.cognitiveRouting = unavailableCapability(
|
|
106
109
|
surfaceState.cognitiveRouting,
|
|
107
110
|
"unavailable",
|
|
108
111
|
"Cognitive Routing could not activate for this session.",
|
|
109
112
|
);
|
|
110
|
-
} else if (!freeflowContext.cognitiveRoutingPrompt) {
|
|
113
|
+
} else if (!isPromptAvailable(freeflowContext.cognitiveRoutingPrompt)) {
|
|
111
114
|
markUnavailable("cognitiveRouting", "Cognitive Routing prompt is unavailable.");
|
|
112
115
|
}
|
|
113
116
|
}
|
|
114
117
|
return surfaceState;
|
|
115
118
|
}
|
|
116
|
-
function modelFacingModeState(modeState, capabilityState) {
|
|
117
|
-
if (capabilityState?.skills?.effective === true) return modeState;
|
|
118
|
-
return { ...modeState, active: false, effectiveMode: null };
|
|
119
|
-
}
|
|
120
119
|
function sessionHasConversationOrRoutingState(ctx) {
|
|
121
120
|
try {
|
|
122
121
|
const entries = ctx?.sessionManager?.getBranch?.() ?? ctx?.sessionManager?.getEntries?.() ?? [];
|
|
@@ -132,50 +131,26 @@ function sessionHasConversationOrRoutingState(ctx) {
|
|
|
132
131
|
}
|
|
133
132
|
return (
|
|
134
133
|
record.type === "custom" &&
|
|
135
|
-
(record.customType === COGNITIVE_ROUTING_INTENT_ENTRY ||
|
|
134
|
+
(record.customType === COGNITIVE_ROUTING_INTENT_ENTRY ||
|
|
135
|
+
record.customType === COGNITIVE_ROUTING_CONTROL_ENTRY ||
|
|
136
|
+
record.customType === COGNITIVE_ROUTING_INACTIVE_ENTRY)
|
|
136
137
|
);
|
|
137
138
|
});
|
|
138
139
|
} catch {
|
|
139
140
|
return false;
|
|
140
141
|
}
|
|
141
142
|
}
|
|
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
143
|
async function applyCapabilityToolVisibility(
|
|
171
144
|
pi,
|
|
172
145
|
ctx,
|
|
173
146
|
capabilityState = undefined,
|
|
174
|
-
|
|
147
|
+
routingSnapshot = {
|
|
148
|
+
status: "available",
|
|
149
|
+
disposition: "available",
|
|
150
|
+
startupSelectionSuppressed: false,
|
|
151
|
+
},
|
|
175
152
|
) {
|
|
176
|
-
if (typeof pi?.setActiveTools !== "function" || typeof pi?.getAllTools !== "function")
|
|
177
|
-
return;
|
|
178
|
-
}
|
|
153
|
+
if (typeof pi?.setActiveTools !== "function" || typeof pi?.getAllTools !== "function") return;
|
|
179
154
|
const state = capabilityState ?? (await readCapabilityState(ctx.cwd, ctx, pi?.host));
|
|
180
155
|
const allToolNames = pi
|
|
181
156
|
.getAllTools()
|
|
@@ -187,12 +162,11 @@ async function applyCapabilityToolVisibility(
|
|
|
187
162
|
(Array.isArray(currentActive) ? currentActive : allToolNames).filter((name) => allToolNameSet.has(name)),
|
|
188
163
|
);
|
|
189
164
|
if (allToolNameSet.has(COGNITIVE_ROUTING_SWITCH_TOOL_NAME)) {
|
|
190
|
-
const controllerState =
|
|
165
|
+
const controllerState = routingSnapshot.runtimeState;
|
|
191
166
|
const routingToolActive =
|
|
192
167
|
state.cognitiveRouting?.effective === true &&
|
|
193
168
|
controllerState?.effective === true &&
|
|
194
|
-
controllerState.controlMode === "automatic"
|
|
195
|
-
!startupSelectionSuppressesCognitiveRouting(ctx);
|
|
169
|
+
controllerState.controlMode === "automatic";
|
|
196
170
|
if (routingToolActive) active.add(COGNITIVE_ROUTING_SWITCH_TOOL_NAME);
|
|
197
171
|
else active.delete(COGNITIVE_ROUTING_SWITCH_TOOL_NAME);
|
|
198
172
|
}
|
|
@@ -205,23 +179,6 @@ async function applyCapabilityToolVisibility(
|
|
|
205
179
|
}
|
|
206
180
|
pi.setActiveTools([...active]);
|
|
207
181
|
}
|
|
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
|
-
]);
|
|
213
|
-
await refreshRuntimeContext(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;
|
|
224
|
-
}
|
|
225
182
|
function disabledToolCall(toolName, capability) {
|
|
226
183
|
const command = capability === "freeflow" ? "/freeflow settings" : `/${capability} settings`;
|
|
227
184
|
return {
|
|
@@ -229,7 +186,7 @@ function disabledToolCall(toolName, capability) {
|
|
|
229
186
|
reason: `${toolName} is disabled by Freeflow config. Configure ${capability} with ${command}.`,
|
|
230
187
|
};
|
|
231
188
|
}
|
|
232
|
-
function freeflowCompletions(prefix,
|
|
189
|
+
function freeflowCompletions(prefix, cognitiveRoutingAvailable = false) {
|
|
233
190
|
const query = prefix ?? "";
|
|
234
191
|
if (query.startsWith("settings ")) {
|
|
235
192
|
const settingsQuery = query.slice("settings ".length);
|
|
@@ -241,27 +198,12 @@ function freeflowCompletions(prefix, hostInfo = undefined) {
|
|
|
241
198
|
.filter((item) => item.value.startsWith(settingsQuery))
|
|
242
199
|
.map((item) => ({ ...item, value: `settings ${item.value}` }));
|
|
243
200
|
}
|
|
244
|
-
if (
|
|
201
|
+
if (cognitiveRoutingAvailable && query.startsWith("profile ")) {
|
|
245
202
|
return cognitiveRoutingProfileCompletions(query.slice("profile ".length)).map((item) => ({
|
|
246
203
|
...item,
|
|
247
204
|
value: `profile ${item.value}`,
|
|
248
205
|
}));
|
|
249
206
|
}
|
|
250
|
-
if (query.startsWith("mode ")) {
|
|
251
|
-
const modeQuery = query.slice("mode ".length);
|
|
252
|
-
return [
|
|
253
|
-
{ value: "conversation", label: "conversation", description: "Read-only discussion and inspection" },
|
|
254
|
-
{ value: "workflow", label: "workflow", description: "Adaptive workflow for consequential work" },
|
|
255
|
-
{ value: "strict-workflow", label: "strict-workflow", description: "Stronger pressure at high-risk boundaries" },
|
|
256
|
-
{
|
|
257
|
-
value: "reset",
|
|
258
|
-
label: "reset",
|
|
259
|
-
description: "Clear the session override and use the configured default",
|
|
260
|
-
},
|
|
261
|
-
]
|
|
262
|
-
.filter((item) => item.value.startsWith(modeQuery))
|
|
263
|
-
.map((item) => ({ ...item, value: `mode ${item.value}` }));
|
|
264
|
-
}
|
|
265
207
|
if (query.startsWith("context ")) {
|
|
266
208
|
const contextQuery = query.slice("context ".length);
|
|
267
209
|
return [
|
|
@@ -277,8 +219,7 @@ function freeflowCompletions(prefix, hostInfo = undefined) {
|
|
|
277
219
|
{ value: "settings", label: "settings", description: "Open personal override settings" },
|
|
278
220
|
{ value: "status", label: "status", description: "Show effective Freeflow state" },
|
|
279
221
|
{ value: "context", label: "context", description: "Inspect Freeflow Context" },
|
|
280
|
-
|
|
281
|
-
...(isPiFlowHost(hostInfo)
|
|
222
|
+
...(cognitiveRoutingAvailable
|
|
282
223
|
? [{ value: "profile", label: "profile", description: "Hold or release Cognitive Routing profile control" }]
|
|
283
224
|
: []),
|
|
284
225
|
{ value: "enable", label: "enable", description: "Enable Freeflow for this repository" },
|
|
@@ -295,7 +236,7 @@ function bypassCompletions(prefix) {
|
|
|
295
236
|
async function sendSkillCommand(pi, ctx, skill, args) {
|
|
296
237
|
const state = await readCapabilityState(ctx.cwd, ctx, pi?.host);
|
|
297
238
|
if (skill === "setup-freeflow" && !state.configured) {
|
|
298
|
-
await pi.sendUserMessage(skillPrompt(skill, args));
|
|
239
|
+
await pi.sendUserMessage(skillPrompt(skill, args), { expandPromptTemplates: true });
|
|
299
240
|
return;
|
|
300
241
|
}
|
|
301
242
|
if (!state.configured) {
|
|
@@ -309,22 +250,26 @@ async function sendSkillCommand(pi, ctx, skill, args) {
|
|
|
309
250
|
);
|
|
310
251
|
return;
|
|
311
252
|
}
|
|
312
|
-
|
|
313
|
-
|
|
253
|
+
const freeflowContext = await getRuntimeContext(state);
|
|
254
|
+
if (!hasUsableMandatoryPrompts(freeflowContext)) {
|
|
255
|
+
ctx.ui.notify("Freeflow core prompts are unavailable; the requested skill cannot be dispatched.", "warning");
|
|
314
256
|
return;
|
|
315
257
|
}
|
|
316
|
-
await pi.sendUserMessage(skillPrompt(skill, args));
|
|
258
|
+
await pi.sendUserMessage(skillPrompt(skill, args), { expandPromptTemplates: true });
|
|
317
259
|
}
|
|
318
260
|
export default function freeflow(pi) {
|
|
319
|
-
|
|
261
|
+
// SAFETY: These helpers register complete Pi tool definitions but retain legacy structural typing for PiFlow compatibility.
|
|
262
|
+
const toolRegistrar = pi;
|
|
263
|
+
const routingSession = new PiRoutingSession({ pi, stockPi: !isPiFlowHost(pi?.host) });
|
|
320
264
|
let latestCognitiveRoutingContext;
|
|
321
265
|
let providerSurfaceSnapshot;
|
|
266
|
+
let runtimeStateRefreshRequired = true;
|
|
322
267
|
let freeflowContextRuntime;
|
|
323
268
|
let contextVirtualizationRuntime;
|
|
324
269
|
let conversationHistoryRuntime;
|
|
325
270
|
const registerContextToolForState = (capabilityState) => {
|
|
326
271
|
registerFreeflowContextTool(
|
|
327
|
-
|
|
272
|
+
toolRegistrar,
|
|
328
273
|
() => contextVirtualizationRuntime,
|
|
329
274
|
() => conversationHistoryRuntime,
|
|
330
275
|
{
|
|
@@ -334,68 +279,81 @@ export default function freeflow(pi) {
|
|
|
334
279
|
);
|
|
335
280
|
};
|
|
336
281
|
const buildProviderSurface = async (ctx, activateCognitiveRouting = false) => {
|
|
337
|
-
const
|
|
338
|
-
readModeState(ctx.cwd),
|
|
339
|
-
readCapabilityState(ctx.cwd, ctx, pi?.host),
|
|
340
|
-
]);
|
|
282
|
+
const capabilityState = await readCapabilityState(ctx.cwd, ctx, pi?.host);
|
|
341
283
|
const freeflowContext = await getRuntimeContext(capabilityState);
|
|
342
284
|
const promptCapabilityState = modelFacingCapabilityState(
|
|
343
285
|
capabilityState,
|
|
344
|
-
ctx,
|
|
345
286
|
freeflowContext,
|
|
346
|
-
|
|
287
|
+
routingSession.snapshot(),
|
|
347
288
|
);
|
|
348
289
|
let activationAttempted = false;
|
|
349
290
|
if (
|
|
350
291
|
activateCognitiveRouting &&
|
|
351
|
-
(
|
|
292
|
+
routingSession.canAutoActivate() &&
|
|
293
|
+
(!routingSession.hasController() || promptCapabilityState.cognitiveRouting?.effective !== true)
|
|
352
294
|
) {
|
|
353
|
-
activationAttempted =
|
|
354
|
-
promptCapabilityState.cognitiveRouting?.effective === true && !startupSelectionSuppressesCognitiveRouting(ctx);
|
|
295
|
+
activationAttempted = promptCapabilityState.cognitiveRouting?.effective === true;
|
|
355
296
|
try {
|
|
356
|
-
|
|
357
|
-
pi,
|
|
297
|
+
await routingSession.reconcileController(
|
|
358
298
|
ctx,
|
|
359
299
|
promptCapabilityState,
|
|
360
|
-
|
|
300
|
+
routingSession.armed ? { ...routingSession.armed } : undefined,
|
|
361
301
|
);
|
|
302
|
+
if (routingSession.hasController()) {
|
|
303
|
+
routingSession.clearArmed();
|
|
304
|
+
if (routingSession.snapshot().status === "active") routingSession.markActive();
|
|
305
|
+
}
|
|
362
306
|
} catch {
|
|
363
|
-
|
|
307
|
+
routingSession.clearController();
|
|
364
308
|
}
|
|
365
309
|
}
|
|
366
310
|
const surfaceCapabilityState = modelFacingCapabilityState(
|
|
367
311
|
promptCapabilityState,
|
|
368
|
-
ctx,
|
|
369
312
|
freeflowContext,
|
|
370
|
-
|
|
371
|
-
activationAttempted && !
|
|
313
|
+
routingSession.snapshot(),
|
|
314
|
+
activationAttempted && !routingSession.hasController(),
|
|
372
315
|
);
|
|
316
|
+
const routingSnapshot = routingSession.snapshot();
|
|
373
317
|
return {
|
|
374
|
-
modeState: modelFacingModeState(modeState, surfaceCapabilityState),
|
|
375
318
|
capabilityState: surfaceCapabilityState,
|
|
376
319
|
freeflowContext,
|
|
377
|
-
cognitiveRoutingRuntime:
|
|
320
|
+
cognitiveRoutingRuntime: routingSnapshot.runtimeState,
|
|
378
321
|
configuredCapabilityState: capabilityState,
|
|
379
322
|
};
|
|
380
323
|
};
|
|
381
324
|
const applyLiveCapabilityStateForSession = async (ctx, options = {}) => {
|
|
382
|
-
|
|
383
|
-
|
|
325
|
+
providerSurfaceSnapshot = undefined;
|
|
326
|
+
await routingSession.applyLiveCapabilityState(ctx, options);
|
|
327
|
+
const capabilityState = await readCapabilityState(ctx.cwd, ctx, pi?.host);
|
|
328
|
+
const freeflowContext = await getRuntimeContext(capabilityState);
|
|
329
|
+
const surfaceCapabilityState = modelFacingCapabilityState(
|
|
330
|
+
capabilityState,
|
|
331
|
+
freeflowContext,
|
|
332
|
+
routingSession.snapshot(),
|
|
333
|
+
);
|
|
334
|
+
const routingSnapshot = routingSession.snapshot();
|
|
335
|
+
setFreeflowStatus(ctx, surfaceCapabilityState, routingSnapshot.runtimeState, freeflowContext, {
|
|
336
|
+
startupSelectionSuppressed: routingSnapshot.startupSelectionSuppressed,
|
|
337
|
+
});
|
|
338
|
+
await applyCapabilityToolVisibility(pi, ctx, surfaceCapabilityState, routingSnapshot);
|
|
339
|
+
registerContextToolForState(surfaceCapabilityState);
|
|
384
340
|
};
|
|
385
|
-
if (
|
|
386
|
-
registerCognitiveRoutingTool(
|
|
387
|
-
registerCognitiveRoutingHistoryTool(
|
|
388
|
-
|
|
389
|
-
|
|
341
|
+
if (routingSession.supportsCognitiveRoutingRuntime()) {
|
|
342
|
+
registerCognitiveRoutingTool(toolRegistrar, () => routingSession.controllerForTool());
|
|
343
|
+
registerCognitiveRoutingHistoryTool(toolRegistrar, (options, context) => {
|
|
344
|
+
return (
|
|
345
|
+
routingSession.history(options) ??
|
|
346
|
+
readCognitiveRoutingHistory(context ?? latestCognitiveRoutingContext, options)
|
|
347
|
+
);
|
|
390
348
|
});
|
|
391
349
|
}
|
|
392
350
|
registerFreeflowContextTool(
|
|
393
|
-
|
|
351
|
+
toolRegistrar,
|
|
394
352
|
() => contextVirtualizationRuntime,
|
|
395
353
|
() => conversationHistoryRuntime,
|
|
396
354
|
{ contextVirtualization: false, conversationHistory: false },
|
|
397
355
|
);
|
|
398
|
-
if (
|
|
356
|
+
if (routingSession.supportsCognitiveRoutingRuntime() && typeof pi.registerShortcut === "function") {
|
|
399
357
|
pi.registerShortcut("ctrl+shift+r", {
|
|
400
358
|
description: "Cycle the Cognitive Routing manual standard/reasoning hold",
|
|
401
359
|
handler: async (ctx) => {
|
|
@@ -403,17 +361,27 @@ export default function freeflow(pi) {
|
|
|
403
361
|
ctx.ui?.notify?.("Freeflow settings and profile changes are available only while Pi is idle.", "warning");
|
|
404
362
|
return;
|
|
405
363
|
}
|
|
406
|
-
|
|
364
|
+
const armedCycle = routingSession.hasController() ? undefined : routingSession.cycleArmedManual();
|
|
365
|
+
if (armedCycle) {
|
|
366
|
+
routingSession.beginExplicitReactivation();
|
|
367
|
+
ctx.ui?.notify?.(`Cognitive Routing manual hold set to ${armedCycle.target}.`, "info");
|
|
368
|
+
await applyLiveCapabilityStateForSession(ctx, {
|
|
369
|
+
reconcileCognitiveRouting: true,
|
|
370
|
+
materializeCognitiveRouting: !isPiFlowHost(pi?.host),
|
|
371
|
+
});
|
|
372
|
+
return;
|
|
373
|
+
}
|
|
374
|
+
if (!routingSession.hasController()) {
|
|
375
|
+
routingSession.beginExplicitReactivation();
|
|
407
376
|
await applyLiveCapabilityStateForSession(ctx, { reconcileCognitiveRouting: true });
|
|
408
377
|
}
|
|
409
|
-
const
|
|
410
|
-
if (!
|
|
378
|
+
const state = routingSession.snapshot().runtimeState;
|
|
379
|
+
if (!state) {
|
|
411
380
|
ctx.ui?.notify?.("Cognitive Routing is unavailable for this session.", "warning");
|
|
412
381
|
return;
|
|
413
382
|
}
|
|
414
|
-
const
|
|
415
|
-
const
|
|
416
|
-
const result = await controller.setManualProfile(target, "profile-shortcut");
|
|
383
|
+
const target = state.activeProfile === "reasoning" ? "standard" : "reasoning";
|
|
384
|
+
const result = await routingSession.setManualProfile(target, "profile-shortcut");
|
|
417
385
|
if (result.status === "active") {
|
|
418
386
|
ctx.ui?.notify?.(`Cognitive Routing manual hold set to ${target}.`, "info");
|
|
419
387
|
} else {
|
|
@@ -423,42 +391,72 @@ export default function freeflow(pi) {
|
|
|
423
391
|
},
|
|
424
392
|
});
|
|
425
393
|
pi.registerShortcut("ctrl+shift+a", {
|
|
426
|
-
description: "
|
|
394
|
+
description: "Set Cognitive Routing to automatic Reasoning control",
|
|
427
395
|
handler: async (ctx) => {
|
|
428
396
|
if (typeof ctx?.isIdle === "function" && !ctx.isIdle()) {
|
|
429
397
|
ctx.ui?.notify?.("Freeflow settings and profile changes are available only while Pi is idle.", "warning");
|
|
430
398
|
return;
|
|
431
399
|
}
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
400
|
+
const armedCycle = routingSession.hasController() ? undefined : routingSession.cycleArmedAutomatic();
|
|
401
|
+
if (armedCycle) {
|
|
402
|
+
if (!armedCycle.changed) {
|
|
403
|
+
ctx.ui?.notify?.("Cognitive Routing automatic control active.", "info");
|
|
404
|
+
return;
|
|
405
|
+
}
|
|
406
|
+
ctx.ui?.notify?.("Cognitive Routing automatic control active.", "info");
|
|
407
|
+
routingSession.beginExplicitReactivation();
|
|
408
|
+
await applyLiveCapabilityStateForSession(ctx, {
|
|
409
|
+
reconcileCognitiveRouting: true,
|
|
410
|
+
materializeCognitiveRouting: !isPiFlowHost(pi?.host),
|
|
411
|
+
});
|
|
438
412
|
return;
|
|
439
413
|
}
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
target,
|
|
446
|
-
`Cycle automatic profile to ${target}.`,
|
|
447
|
-
"user",
|
|
448
|
-
"profile-shortcut",
|
|
449
|
-
)
|
|
450
|
-
: await controller.setAutomaticControl("profile-shortcut");
|
|
414
|
+
if (!routingSession.hasController()) {
|
|
415
|
+
routingSession.beginExplicitReactivation();
|
|
416
|
+
await applyLiveCapabilityStateForSession(ctx, { reconcileCognitiveRouting: true });
|
|
417
|
+
}
|
|
418
|
+
const result = await routingSession.setAutomaticControl("profile-shortcut");
|
|
451
419
|
if (result.status === "automatic") {
|
|
452
420
|
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
421
|
} else {
|
|
456
|
-
ctx.ui?.notify?.(`Cognitive Routing could not
|
|
422
|
+
ctx.ui?.notify?.(`Cognitive Routing could not change control: ${result.reason}.`, "warning");
|
|
457
423
|
}
|
|
458
424
|
await applyLiveCapabilityStateForSession(ctx);
|
|
459
425
|
},
|
|
460
426
|
});
|
|
461
427
|
}
|
|
428
|
+
if (!isPiFlowHost(pi?.host) && routingSession.supportsCognitiveRoutingRuntime()) {
|
|
429
|
+
pi.on("model_select", async (event, ctx) => {
|
|
430
|
+
if (!routingSession.hasController()) {
|
|
431
|
+
if (!routingSession.armed) return;
|
|
432
|
+
routingSession.clearArmed();
|
|
433
|
+
routingSession.observeArmedNativeChange(ctx, "Pi model selection");
|
|
434
|
+
await applyLiveCapabilityStateForSession(ctx);
|
|
435
|
+
return;
|
|
436
|
+
}
|
|
437
|
+
const result = await routingSession.observeNativeChange("Pi model selection", event?.source);
|
|
438
|
+
if (result.status !== "ignored") {
|
|
439
|
+
latestCognitiveRoutingContext = ctx;
|
|
440
|
+
providerSurfaceSnapshot = undefined;
|
|
441
|
+
await applyLiveCapabilityStateForSession(ctx);
|
|
442
|
+
}
|
|
443
|
+
});
|
|
444
|
+
pi.on("thinking_level_select", async (_event, ctx) => {
|
|
445
|
+
if (!routingSession.hasController()) {
|
|
446
|
+
if (!routingSession.armed) return;
|
|
447
|
+
routingSession.clearArmed();
|
|
448
|
+
routingSession.observeArmedNativeChange(ctx, "Pi thinking-level selection");
|
|
449
|
+
await applyLiveCapabilityStateForSession(ctx);
|
|
450
|
+
return;
|
|
451
|
+
}
|
|
452
|
+
const result = await routingSession.observeNativeChange("Pi thinking-level selection");
|
|
453
|
+
if (result.status !== "ignored") {
|
|
454
|
+
latestCognitiveRoutingContext = ctx;
|
|
455
|
+
providerSurfaceSnapshot = undefined;
|
|
456
|
+
await applyLiveCapabilityStateForSession(ctx);
|
|
457
|
+
}
|
|
458
|
+
});
|
|
459
|
+
}
|
|
462
460
|
pi.on("resources_discover", async (event, ctx) => {
|
|
463
461
|
const cwd = ctx?.cwd ?? event?.cwd ?? process.cwd();
|
|
464
462
|
const snapshot =
|
|
@@ -469,15 +467,17 @@ export default function freeflow(pi) {
|
|
|
469
467
|
if (!state.configured) {
|
|
470
468
|
return { skillPaths: [freeflowSkillPath("setup-freeflow")] };
|
|
471
469
|
}
|
|
472
|
-
if (!state.enabled || !
|
|
470
|
+
if (!state.enabled || !hasUsableMandatoryPrompts(snapshot.freeflowContext)) {
|
|
473
471
|
return { skillPaths: [] };
|
|
474
472
|
}
|
|
475
473
|
return { skillPaths: freeflowModelSkillPaths(state) };
|
|
476
474
|
});
|
|
477
|
-
pi.on("session_start", async (
|
|
475
|
+
pi.on("session_start", async (event, ctx) => {
|
|
476
|
+
routingSession.resetForSession(ctx, event);
|
|
478
477
|
latestCognitiveRoutingContext = ctx;
|
|
479
478
|
providerSurfaceSnapshot = undefined;
|
|
480
|
-
|
|
479
|
+
runtimeStateRefreshRequired = true;
|
|
480
|
+
restoreSessionOverrides(ctx);
|
|
481
481
|
freeflowContextRuntime = new FreeflowContextRuntime(ctx);
|
|
482
482
|
contextVirtualizationRuntime = new ContextVirtualizationRuntime(pi, ctx, freeflowContextRuntime);
|
|
483
483
|
conversationHistoryRuntime = new ConversationHistoryRuntime(
|
|
@@ -488,38 +488,48 @@ export default function freeflow(pi) {
|
|
|
488
488
|
await contextVirtualizationRuntime.recover(ctx);
|
|
489
489
|
const capabilityState = await readCapabilityState(ctx.cwd, ctx, pi?.host);
|
|
490
490
|
await refreshRuntimeContext(capabilityState);
|
|
491
|
+
routingSession.ensureStartupInactive(ctx, capabilityState.cognitiveRouting?.effective === true);
|
|
492
|
+
routingSession.reconcileNativeEntries(ctx);
|
|
491
493
|
const hasSessionState = sessionHasConversationOrRoutingState(ctx);
|
|
492
494
|
const snapshot = await buildProviderSurface(ctx, hasSessionState);
|
|
493
|
-
|
|
494
|
-
snapshot.capabilityState?.cognitiveRouting?.effective === true &&
|
|
495
|
+
if (
|
|
495
496
|
!hasSessionState &&
|
|
496
|
-
|
|
497
|
+
snapshot.capabilityState?.cognitiveRouting?.effective === true &&
|
|
498
|
+
routingSession.canAutoActivate()
|
|
499
|
+
) {
|
|
500
|
+
routingSession.armFromCapability(snapshot.capabilityState.cognitiveRouting);
|
|
501
|
+
} else {
|
|
502
|
+
routingSession.clearArmed();
|
|
503
|
+
}
|
|
497
504
|
registerContextToolForState(snapshot.capabilityState);
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
505
|
+
const routingSnapshot = routingSession.snapshot();
|
|
506
|
+
setFreeflowStatus(
|
|
507
|
+
ctx,
|
|
508
|
+
snapshot.capabilityState,
|
|
509
|
+
snapshot.cognitiveRoutingRuntime ?? routingSnapshot.runtimeState,
|
|
510
|
+
snapshot.freeflowContext,
|
|
511
|
+
{ startupSelectionSuppressed: routingSnapshot.startupSelectionSuppressed },
|
|
512
|
+
);
|
|
513
|
+
await applyCapabilityToolVisibility(pi, ctx, snapshot.capabilityState, routingSnapshot);
|
|
502
514
|
});
|
|
503
515
|
pi.on("agent_settled", async (_event, ctx) => {
|
|
504
|
-
if (!
|
|
516
|
+
if (!routingSession.hasController()) return undefined;
|
|
505
517
|
await applyLiveCapabilityStateForSession(ctx);
|
|
506
518
|
return undefined;
|
|
507
519
|
});
|
|
508
520
|
pi.on("session_shutdown", async (event) => {
|
|
521
|
+
await routingSession.shutdown(event?.reason);
|
|
509
522
|
providerSurfaceSnapshot = undefined;
|
|
510
|
-
const controller = cognitiveRoutingController;
|
|
511
|
-
cognitiveRoutingController = undefined;
|
|
512
523
|
freeflowContextRuntime = undefined;
|
|
513
524
|
contextVirtualizationRuntime = undefined;
|
|
514
525
|
conversationHistoryRuntime = undefined;
|
|
515
|
-
if (controller) await controller.shutdown(event?.reason);
|
|
516
526
|
});
|
|
517
527
|
pi.on("session_tree", async (_event, ctx) => {
|
|
518
528
|
latestCognitiveRoutingContext = ctx;
|
|
519
529
|
providerSurfaceSnapshot = undefined;
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
530
|
+
runtimeStateRefreshRequired = true;
|
|
531
|
+
restoreSessionOverrides(ctx);
|
|
532
|
+
await routingSession.reconcileBranch();
|
|
523
533
|
if (contextVirtualizationRuntime) {
|
|
524
534
|
contextVirtualizationRuntime.setContext(ctx);
|
|
525
535
|
await contextVirtualizationRuntime.recover(ctx);
|
|
@@ -530,29 +540,25 @@ export default function freeflow(pi) {
|
|
|
530
540
|
pi.on("session_compact", async (_event, ctx) => {
|
|
531
541
|
latestCognitiveRoutingContext = ctx;
|
|
532
542
|
providerSurfaceSnapshot = undefined;
|
|
533
|
-
|
|
534
|
-
|
|
543
|
+
runtimeStateRefreshRequired = true;
|
|
544
|
+
await routingSession.reconcileBranch("session-compact");
|
|
535
545
|
if (contextVirtualizationRuntime) {
|
|
536
546
|
contextVirtualizationRuntime.setContext(ctx);
|
|
537
547
|
await contextVirtualizationRuntime.recover(ctx);
|
|
538
548
|
}
|
|
539
549
|
conversationHistoryRuntime?.setContext(ctx);
|
|
540
|
-
|
|
541
|
-
readModeState(ctx.cwd),
|
|
542
|
-
readCapabilityState(ctx.cwd, ctx, pi?.host),
|
|
543
|
-
]);
|
|
544
|
-
await refreshRuntimeContext(capabilityState);
|
|
545
|
-
registerContextToolForState(capabilityState);
|
|
546
|
-
setModeStatus(ctx, modeState, capabilityState, cognitiveRoutingController?.state());
|
|
547
|
-
await applyCapabilityToolVisibility(pi, ctx, capabilityState, cognitiveRoutingController);
|
|
550
|
+
await applyLiveCapabilityStateForSession(ctx);
|
|
548
551
|
});
|
|
549
552
|
pi.on("before_agent_start", async (event, ctx) => {
|
|
550
553
|
latestCognitiveRoutingContext = ctx;
|
|
551
554
|
const snapshot = await buildProviderSurface(ctx, true);
|
|
552
555
|
providerSurfaceSnapshot = { context: ctx, value: snapshot };
|
|
553
556
|
registerContextToolForState(snapshot.capabilityState);
|
|
554
|
-
|
|
555
|
-
|
|
557
|
+
const routingSnapshot = routingSession.snapshot();
|
|
558
|
+
setFreeflowStatus(ctx, snapshot.capabilityState, snapshot.cognitiveRoutingRuntime, snapshot.freeflowContext, {
|
|
559
|
+
startupSelectionSuppressed: routingSnapshot.startupSelectionSuppressed,
|
|
560
|
+
});
|
|
561
|
+
await applyCapabilityToolVisibility(pi, ctx, snapshot.capabilityState, routingSnapshot);
|
|
556
562
|
const freeflowRuntimeContext = runtimeContext(snapshot.freeflowContext, snapshot.capabilityState);
|
|
557
563
|
const systemPrompt = freeflowRuntimeContext
|
|
558
564
|
? `${event.systemPrompt}\n\n${freeflowRuntimeContext}`
|
|
@@ -565,7 +571,6 @@ export default function freeflow(pi) {
|
|
|
565
571
|
if (providerSurfaceSnapshot?.context === ctx) providerSurfaceSnapshot = undefined;
|
|
566
572
|
const cognitiveRoutingRuntime = snapshot.cognitiveRoutingRuntime;
|
|
567
573
|
const surfaceCapabilityState = snapshot.capabilityState;
|
|
568
|
-
const surfaceModeState = snapshot.modeState;
|
|
569
574
|
let changed = false;
|
|
570
575
|
let messages = event.messages
|
|
571
576
|
.map((message) => {
|
|
@@ -589,14 +594,19 @@ export default function freeflow(pi) {
|
|
|
589
594
|
conversationHistoryRuntime.setContext(ctx);
|
|
590
595
|
conversationHistoryRuntime.capture(surfaceCapabilityState.contextVirtualization?.effective === true);
|
|
591
596
|
}
|
|
597
|
+
const forceRuntimeStateRefresh = runtimeStateRefreshRequired;
|
|
592
598
|
const nextMessages = withFreeflowRuntimeState(
|
|
593
599
|
messages,
|
|
594
|
-
surfaceModeState,
|
|
595
600
|
surfaceCapabilityState,
|
|
596
601
|
cognitiveRoutingRuntime,
|
|
602
|
+
snapshot.freeflowContext,
|
|
603
|
+
{ force: forceRuntimeStateRefresh },
|
|
597
604
|
);
|
|
598
|
-
|
|
599
|
-
|
|
605
|
+
if (nextMessages !== messages) {
|
|
606
|
+
changed = true;
|
|
607
|
+
messages = nextMessages;
|
|
608
|
+
}
|
|
609
|
+
if (forceRuntimeStateRefresh) runtimeStateRefreshRequired = false;
|
|
600
610
|
return changed ? { messages } : undefined;
|
|
601
611
|
});
|
|
602
612
|
pi.on("tool_call", async (event, ctx) => {
|
|
@@ -613,7 +623,7 @@ export default function freeflow(pi) {
|
|
|
613
623
|
});
|
|
614
624
|
pi.on("tool_result", async (event, ctx) => {
|
|
615
625
|
const toolName = typeof event?.toolName === "string" ? event.toolName : "";
|
|
616
|
-
if (
|
|
626
|
+
if (routingSession.supportsCognitiveRoutingRuntime() && toolName === COGNITIVE_ROUTING_SWITCH_TOOL_NAME) {
|
|
617
627
|
await applyLiveCapabilityStateForSession(ctx);
|
|
618
628
|
}
|
|
619
629
|
return undefined;
|
|
@@ -637,7 +647,7 @@ export default function freeflow(pi) {
|
|
|
637
647
|
}
|
|
638
648
|
pi.registerCommand("freeflow", {
|
|
639
649
|
description: "Open unified Freeflow settings or print compact status",
|
|
640
|
-
getArgumentCompletions: (prefix) => freeflowCompletions(prefix,
|
|
650
|
+
getArgumentCompletions: (prefix) => freeflowCompletions(prefix, routingSession.supportsCognitiveRoutingRuntime()),
|
|
641
651
|
handler: async (args, ctx) => {
|
|
642
652
|
const contextInput = (args ?? "").trim();
|
|
643
653
|
if (contextInput === "context" || contextInput.startsWith("context ")) {
|
|
@@ -651,23 +661,30 @@ export default function freeflow(pi) {
|
|
|
651
661
|
);
|
|
652
662
|
return;
|
|
653
663
|
}
|
|
654
|
-
if (
|
|
664
|
+
if (routingSession.supportsCognitiveRoutingRuntime() && /^profile(?:\s|$)/i.test((args ?? "").trim())) {
|
|
655
665
|
const profileCommandContext = {
|
|
656
666
|
isIdle: ctx?.isIdle,
|
|
657
667
|
ui: ctx?.ui,
|
|
658
|
-
history: (options) =>
|
|
659
|
-
cognitiveRoutingController?.history(options) ?? readCognitiveRoutingHistory(ctx, options),
|
|
668
|
+
history: (options) => routingSession.history(options) ?? readCognitiveRoutingHistory(ctx, options),
|
|
660
669
|
};
|
|
661
670
|
const historyCommand = /^profile\s+history(?:\s|$)/i.test((args ?? "").trim());
|
|
662
671
|
if (historyCommand) {
|
|
663
|
-
await handleCognitiveRoutingProfileCommand(args, profileCommandContext,
|
|
672
|
+
await handleCognitiveRoutingProfileCommand(args, profileCommandContext, routingSession.commandController());
|
|
664
673
|
return;
|
|
665
674
|
}
|
|
666
|
-
if (!
|
|
675
|
+
if (!routingSession.hasController() && !routingSession.armed) {
|
|
676
|
+
routingSession.beginExplicitReactivation();
|
|
667
677
|
await applyLiveCapabilityStateForSession(ctx, { reconcileCognitiveRouting: true });
|
|
668
678
|
}
|
|
669
|
-
|
|
670
|
-
|
|
679
|
+
const profileController = routingSession.commandController();
|
|
680
|
+
if (await handleCognitiveRoutingProfileCommand(args, profileCommandContext, profileController)) {
|
|
681
|
+
if (profileController) {
|
|
682
|
+
routingSession.beginExplicitReactivation();
|
|
683
|
+
await applyLiveCapabilityStateForSession(ctx, {
|
|
684
|
+
reconcileCognitiveRouting: routingSession.armed !== undefined,
|
|
685
|
+
materializeCognitiveRouting: routingSession.armed !== undefined && !isPiFlowHost(pi?.host),
|
|
686
|
+
});
|
|
687
|
+
}
|
|
671
688
|
return;
|
|
672
689
|
}
|
|
673
690
|
}
|
|
@@ -680,7 +697,7 @@ export default function freeflow(pi) {
|
|
|
680
697
|
});
|
|
681
698
|
},
|
|
682
699
|
pi,
|
|
683
|
-
|
|
700
|
+
routingSession.commandController(),
|
|
684
701
|
);
|
|
685
702
|
},
|
|
686
703
|
});
|