@hassangameryt/freeflow 0.6.0 → 0.7.1
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 +3 -2
- package/.codex-plugin/plugin.json +5 -6
- package/.cursor-plugin/plugin.json +25 -0
- package/README.md +66 -56
- package/capabilities/cognitive-routing/SKILL.md +288 -130
- package/com.github.copilot/hooks/hooks.json +11 -0
- package/command-surface.json +0 -24
- package/gemini-extension.json +5 -0
- package/hooks/adapters/claude-session-start.mjs +16 -0
- package/hooks/adapters/codex-session-start.mjs +16 -0
- package/hooks/adapters/copilot-session-start.mjs +13 -0
- package/hooks/adapters/cursor-session-start.mjs +13 -0
- package/hooks/adapters/gemini-session-start.mjs +15 -0
- package/hooks/claude/hooks.json +18 -0
- package/hooks/codex/hooks.json +18 -0
- package/hooks/cursor/hooks.json +9 -0
- package/hooks/freeflow-runtime-context.mjs +3 -650
- package/hooks/hooks.json +4 -30
- package/hooks/shared/runtime-context.mjs +210 -0
- package/hooks/tests/check-host-adapters.test.mjs +82 -0
- package/hooks/tests/check-runtime-context-hook.sh +140 -320
- package/package.json +20 -4
- 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/plugin.json +33 -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
|
@@ -3,35 +3,19 @@ import { appendFile, mkdir, readFile, rm, writeFile } from "node:fs/promises";
|
|
|
3
3
|
import { dirname, isAbsolute, join, resolve } from "node:path";
|
|
4
4
|
import { promisify } from "node:util";
|
|
5
5
|
import {
|
|
6
|
-
handleModeCommand,
|
|
7
6
|
readCapabilityState,
|
|
8
7
|
readFreeflowConfig,
|
|
9
8
|
readFreeflowConfigLayers,
|
|
10
9
|
readFreeflowLocalConfig,
|
|
11
|
-
readModeState,
|
|
12
10
|
resetSessionOverrides,
|
|
13
11
|
setSessionCoreOverride,
|
|
14
|
-
VALID_MODES,
|
|
15
12
|
} from "../runtime/runtime-context.js";
|
|
16
13
|
import { PiSettingsComponent } from "./settings-tui.js";
|
|
14
|
+
import { supportsPiSessionModelStateApi } from "../cognitive-routing/pi-session-control.js";
|
|
17
15
|
import { isPiFlowHost } from "../runtime/runtime-identity.js";
|
|
18
16
|
const DEFAULT_FREEFLOW_ENABLED = true;
|
|
19
|
-
const DEFAULT_INTERACTION_CONTRACT_ENABLED = true;
|
|
20
|
-
const DEFAULT_SKILLS_ENABLED = true;
|
|
21
17
|
const DEFAULT_CONTEXT_VIRTUALIZATION_ENABLED = false;
|
|
22
18
|
const DEFAULT_CONVERSATION_HISTORY_ENABLED = false;
|
|
23
|
-
const MODE_VALUES = ["conversation", "workflow", "strict-workflow"];
|
|
24
|
-
const MODE_LABELS = {
|
|
25
|
-
default: "Use configured default",
|
|
26
|
-
conversation: "conversation",
|
|
27
|
-
workflow: "workflow",
|
|
28
|
-
"strict-workflow": "strict-workflow",
|
|
29
|
-
};
|
|
30
|
-
const MODE_DESCRIPTIONS = {
|
|
31
|
-
conversation: "Discussion and read-only inspection",
|
|
32
|
-
workflow: "Adaptive workflow for consequential work",
|
|
33
|
-
"strict-workflow": "Stronger decision and evidence pressure for high-risk work",
|
|
34
|
-
};
|
|
35
19
|
const LOCAL_INHERIT = "inherit";
|
|
36
20
|
const execFileAsync = promisify(execFile);
|
|
37
21
|
function isRecord(value) {
|
|
@@ -208,83 +192,18 @@ function createScopedBooleanItem(options) {
|
|
|
208
192
|
item.displaySuffix = coreDisplaySuffix(item);
|
|
209
193
|
return item;
|
|
210
194
|
}
|
|
211
|
-
function createScopedDefaultModeItem(options) {
|
|
212
|
-
let item;
|
|
213
|
-
if (options.scope === "local") {
|
|
214
|
-
item = {
|
|
215
|
-
id: "freeflow.defaultMode",
|
|
216
|
-
label: "Default mode",
|
|
217
|
-
description:
|
|
218
|
-
"Personal default mode for this checkout. Choose inherit to use the repository default; use /freeflow settings repo to edit shared defaults.",
|
|
219
|
-
path: ["defaultMode"],
|
|
220
|
-
kind: "enum",
|
|
221
|
-
value: options.localDefaultMode ?? LOCAL_INHERIT,
|
|
222
|
-
values: [LOCAL_INHERIT, ...MODE_VALUES],
|
|
223
|
-
valueLabels: {
|
|
224
|
-
inherit: "Inherit repository",
|
|
225
|
-
...MODE_LABELS,
|
|
226
|
-
},
|
|
227
|
-
valueDescriptions: {
|
|
228
|
-
inherit: `Use ${options.repositoryDefaultMode} from ${options.repositoryDefaultSource}.`,
|
|
229
|
-
...MODE_DESCRIPTIONS,
|
|
230
|
-
},
|
|
231
|
-
format: (value) => String(value),
|
|
232
|
-
configScope: "local",
|
|
233
|
-
configValues: { inherit: undefined },
|
|
234
|
-
effectiveValue: options.effectiveValue,
|
|
235
|
-
effectiveSource: options.effectiveSource,
|
|
236
|
-
inheritedValue: options.repositoryDefaultMode,
|
|
237
|
-
inheritedSource: options.repositoryDefaultSource,
|
|
238
|
-
};
|
|
239
|
-
} else {
|
|
240
|
-
item = {
|
|
241
|
-
id: "freeflow.defaultMode",
|
|
242
|
-
label: "Default mode",
|
|
243
|
-
description:
|
|
244
|
-
"Shared repository default Freeflow mode used when Skills are enabled. This edits .freeflow/config.json.",
|
|
245
|
-
path: ["defaultMode"],
|
|
246
|
-
kind: "enum",
|
|
247
|
-
value: options.repositoryDefaultMode,
|
|
248
|
-
values: MODE_VALUES,
|
|
249
|
-
valueLabels: MODE_LABELS,
|
|
250
|
-
valueDescriptions: MODE_DESCRIPTIONS,
|
|
251
|
-
configScope: "repository",
|
|
252
|
-
effectiveValue: options.effectiveValue,
|
|
253
|
-
effectiveSource: options.effectiveSource,
|
|
254
|
-
localOverrideValue: options.localDefaultMode,
|
|
255
|
-
};
|
|
256
|
-
}
|
|
257
|
-
item.displaySuffix = coreDisplaySuffix(item);
|
|
258
|
-
return item;
|
|
259
|
-
}
|
|
260
|
-
function sessionModeDisplaySuffix(sessionMode, defaultMode, defaultSource, inactive) {
|
|
261
|
-
if (sessionMode !== "default") return undefined;
|
|
262
|
-
const inactiveSuffix = inactive ? " · inactive" : "";
|
|
263
|
-
return `(${defaultMode} · ${defaultSource}${inactiveSuffix})`;
|
|
264
|
-
}
|
|
265
|
-
function validModeOrUndefined(value) {
|
|
266
|
-
return typeof value === "string" && VALID_MODES.has(value) ? value : undefined;
|
|
267
|
-
}
|
|
268
195
|
function resolveSettingsCoreView(rawConfig, layers) {
|
|
269
196
|
const localConfig = layers?.local.valid && isRecord(layers.local.parsed) ? layers.local.parsed : {};
|
|
270
|
-
const repositorySkillsValue = getPath(rawConfig, ["skills"]);
|
|
271
|
-
const repositorySkills = isRecord(repositorySkillsValue) ? repositorySkillsValue : {};
|
|
272
197
|
const fallbackCore = {
|
|
273
198
|
enabled: getPath(rawConfig, ["enabled"]) !== false,
|
|
274
|
-
interactionContract: getPath(rawConfig, ["interactionContract"]) !== false,
|
|
275
199
|
contextVirtualization: getPath(rawConfig, ["contextVirtualization"]) === true,
|
|
276
200
|
conversationHistory: getPath(rawConfig, ["conversationHistory"]) === true,
|
|
277
|
-
skills: { enabled: getPath(repositorySkills, ["enabled"]) !== false },
|
|
278
|
-
defaultMode: validModeOrUndefined(rawConfig.defaultMode) ?? "workflow",
|
|
279
201
|
};
|
|
280
202
|
const fallbackSources = {
|
|
281
203
|
enabled: typeof getPath(rawConfig, ["enabled"]) === "boolean" ? "repository" : "builtin",
|
|
282
|
-
interactionContract: typeof getPath(rawConfig, ["interactionContract"]) === "boolean" ? "repository" : "builtin",
|
|
283
204
|
contextVirtualization:
|
|
284
205
|
typeof getPath(rawConfig, ["contextVirtualization"]) === "boolean" ? "repository" : "builtin",
|
|
285
206
|
conversationHistory: typeof getPath(rawConfig, ["conversationHistory"]) === "boolean" ? "repository" : "builtin",
|
|
286
|
-
skillsEnabled: typeof getPath(repositorySkills, ["enabled"]) === "boolean" ? "repository" : "builtin",
|
|
287
|
-
defaultMode: validModeOrUndefined(rawConfig.defaultMode) === undefined ? "builtin" : "repository",
|
|
288
207
|
};
|
|
289
208
|
return {
|
|
290
209
|
localConfig,
|
|
@@ -329,7 +248,7 @@ function createSessionBooleanItem(options) {
|
|
|
329
248
|
item.displaySuffix = coreDisplaySuffix(item);
|
|
330
249
|
return item;
|
|
331
250
|
}
|
|
332
|
-
function sessionFreeflowItems(state,
|
|
251
|
+
function sessionFreeflowItems(state, cognitiveRoutingController) {
|
|
333
252
|
const sessionOverrides = state.sessionOverrides;
|
|
334
253
|
const configured = state.configuredCoreConfig;
|
|
335
254
|
const configuredSources = state.configuredSources;
|
|
@@ -345,28 +264,6 @@ function sessionFreeflowItems(state, modeState, cognitiveRoutingController) {
|
|
|
345
264
|
effectiveSource: effectiveSources.enabled,
|
|
346
265
|
sessionOverrides,
|
|
347
266
|
});
|
|
348
|
-
const interactionItem = createSessionBooleanItem({
|
|
349
|
-
id: "freeflow.interactionContract",
|
|
350
|
-
label: "Interaction Contract",
|
|
351
|
-
description: "Temporary Interaction Contract override for this Pi session.",
|
|
352
|
-
key: "interactionContract",
|
|
353
|
-
inheritedValue: configured.interactionContract,
|
|
354
|
-
inheritedSource: configuredSources.interactionContract,
|
|
355
|
-
effectiveValue: state.interactionContract.enabled,
|
|
356
|
-
effectiveSource: effectiveSources.interactionContract,
|
|
357
|
-
sessionOverrides,
|
|
358
|
-
});
|
|
359
|
-
const skillsItem = createSessionBooleanItem({
|
|
360
|
-
id: "freeflow.skills.enabled",
|
|
361
|
-
label: "Skills",
|
|
362
|
-
description: "Temporary Freeflow Skills override for this Pi session.",
|
|
363
|
-
key: "skillsEnabled",
|
|
364
|
-
inheritedValue: configured.skills.enabled,
|
|
365
|
-
inheritedSource: configuredSources.skillsEnabled,
|
|
366
|
-
effectiveValue: state.skills.enabled,
|
|
367
|
-
effectiveSource: effectiveSources.skillsEnabled,
|
|
368
|
-
sessionOverrides,
|
|
369
|
-
});
|
|
370
267
|
const contextVirtualizationItem = createSessionBooleanItem({
|
|
371
268
|
id: "freeflow.contextVirtualization",
|
|
372
269
|
label: "Context Virtualization",
|
|
@@ -390,37 +287,8 @@ function sessionFreeflowItems(state, modeState, cognitiveRoutingController) {
|
|
|
390
287
|
sessionOverrides,
|
|
391
288
|
});
|
|
392
289
|
const freeflowInactive = !state.enabled;
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
skillsItem.inactive = freeflowInactive;
|
|
396
|
-
contextVirtualizationItem.inactive = freeflowInactive || !skillsEnabled;
|
|
397
|
-
conversationHistoryItem.inactive = freeflowInactive || !skillsEnabled;
|
|
398
|
-
const sessionMode = modeState.currentMode ?? "default";
|
|
399
|
-
const sessionModeItem = {
|
|
400
|
-
id: "freeflow.sessionMode",
|
|
401
|
-
label: "Mode",
|
|
402
|
-
description: "Temporary mode override for this Pi session.",
|
|
403
|
-
kind: "enum",
|
|
404
|
-
value: sessionMode,
|
|
405
|
-
values: ["default", ...MODE_VALUES],
|
|
406
|
-
valueLabels: {
|
|
407
|
-
...MODE_LABELS,
|
|
408
|
-
default: "Use configured default",
|
|
409
|
-
},
|
|
410
|
-
valueDescriptions: {
|
|
411
|
-
default: `${modeState.defaultMode} from ${modeState.defaultModeSource}`,
|
|
412
|
-
...MODE_DESCRIPTIONS,
|
|
413
|
-
},
|
|
414
|
-
inactive: freeflowInactive || !skillsEnabled,
|
|
415
|
-
displaySuffix: sessionModeDisplaySuffix(
|
|
416
|
-
sessionMode,
|
|
417
|
-
modeState.defaultMode,
|
|
418
|
-
modeState.defaultModeSource,
|
|
419
|
-
freeflowInactive || !skillsEnabled,
|
|
420
|
-
),
|
|
421
|
-
inheritedValue: modeState.defaultMode,
|
|
422
|
-
inheritedSource: modeState.defaultModeSource,
|
|
423
|
-
};
|
|
290
|
+
contextVirtualizationItem.inactive = freeflowInactive;
|
|
291
|
+
conversationHistoryItem.inactive = freeflowInactive;
|
|
424
292
|
const cognitiveRoutingState = cognitiveRoutingController?.state();
|
|
425
293
|
const cognitiveRoutingProfile =
|
|
426
294
|
cognitiveRoutingState?.controlMode === "manual-standard"
|
|
@@ -446,22 +314,18 @@ function sessionFreeflowItems(state, modeState, cognitiveRoutingController) {
|
|
|
446
314
|
standard: "Hold the standard profile until /freeflow profile auto.",
|
|
447
315
|
reasoning: "Hold the reasoning profile until /freeflow profile auto.",
|
|
448
316
|
},
|
|
449
|
-
inactive: !state.cognitiveRouting.effective || cognitiveRoutingController === undefined,
|
|
317
|
+
inactive: freeflowInactive || !state.cognitiveRouting.effective || cognitiveRoutingController === undefined,
|
|
450
318
|
runtimeInactive: state.cognitiveRouting.blockingReason?.code === "runtime_disabled",
|
|
451
319
|
displaySuffix: cognitiveRoutingState?.effective ? cognitiveRoutingProfile : "unavailable",
|
|
452
320
|
}
|
|
453
321
|
: undefined;
|
|
454
322
|
return [
|
|
455
323
|
freeflowItem,
|
|
456
|
-
interactionItem,
|
|
457
|
-
skillsItem,
|
|
458
|
-
sessionModeItem,
|
|
459
324
|
...(cognitiveRoutingItem ? [cognitiveRoutingItem] : []),
|
|
460
325
|
{
|
|
461
326
|
id: "freeflow.session.reset",
|
|
462
327
|
label: "Reset session overrides",
|
|
463
|
-
description:
|
|
464
|
-
"Clear Freeflow, Interaction Contract, Skills, Context Virtualization, Conversation History, and mode overrides for this Pi session.",
|
|
328
|
+
description: "Clear Freeflow, Context Virtualization, and Conversation History overrides for this Pi session.",
|
|
465
329
|
kind: "enum",
|
|
466
330
|
value: "available",
|
|
467
331
|
values: ["reset"],
|
|
@@ -688,18 +552,18 @@ function cognitiveRoutingProfileItem(options) {
|
|
|
688
552
|
}
|
|
689
553
|
function cognitiveRoutingSessionStartItem(options) {
|
|
690
554
|
const path = ["cognitiveRouting", "sessionStart", options.setting];
|
|
691
|
-
const defaultValue = options.setting === "control" ? "automatic" : "
|
|
555
|
+
const defaultValue = options.setting === "control" ? "automatic" : "reasoning";
|
|
692
556
|
const values = options.setting === "control" ? ["automatic", "manual"] : ["standard", "reasoning"];
|
|
693
557
|
const labels = Object.fromEntries(values.map((value) => [value, value]));
|
|
694
558
|
const descriptions =
|
|
695
559
|
options.setting === "control"
|
|
696
560
|
? {
|
|
697
|
-
automatic: "
|
|
561
|
+
automatic: "Start the new session in Reasoning; automatic delegation may use Standard during execution.",
|
|
698
562
|
manual: "Hold the selected profile for the new session until the user changes it.",
|
|
699
563
|
}
|
|
700
564
|
: {
|
|
701
|
-
standard: "Start a new session with the configured Standard preset.",
|
|
702
|
-
reasoning: "Start a new session with the configured Reasoning preset.",
|
|
565
|
+
standard: "Start a new manual session with the configured Standard preset.",
|
|
566
|
+
reasoning: "Start a new manual session with the configured Reasoning preset.",
|
|
703
567
|
};
|
|
704
568
|
const repositoryValue = getPath(options.rawConfig, path);
|
|
705
569
|
const localValue = getPath(options.localConfig, path);
|
|
@@ -710,13 +574,21 @@ function cognitiveRoutingSessionStartItem(options) {
|
|
|
710
574
|
const inheritedSource = repositorySetting ? "repository" : "builtin";
|
|
711
575
|
const configuredSource =
|
|
712
576
|
options.capabilityState?.sessionStartSources?.[options.setting] ?? (repositorySetting ? "repository" : undefined);
|
|
713
|
-
const
|
|
577
|
+
const effectiveSessionStartControl =
|
|
578
|
+
options.capabilityState?.sessionStart?.control ??
|
|
579
|
+
getPath(options.localConfig, ["cognitiveRouting", "sessionStart", "control"]) ??
|
|
580
|
+
getPath(options.rawConfig, ["cognitiveRouting", "sessionStart", "control"]) ??
|
|
581
|
+
"automatic";
|
|
582
|
+
const effectiveValue =
|
|
583
|
+
options.setting === "profile" && effectiveSessionStartControl === "automatic"
|
|
584
|
+
? "reasoning"
|
|
585
|
+
: (options.capabilityState?.sessionStart?.[options.setting] ?? inheritedValue);
|
|
714
586
|
const effectiveSource = cognitiveRoutingSettingsSource(configuredSource);
|
|
715
|
-
const label = options.setting === "control" ? "Session start control" : "
|
|
587
|
+
const label = options.setting === "control" ? "Session start control" : "Manual session-start profile";
|
|
716
588
|
const description =
|
|
717
589
|
options.setting === "control"
|
|
718
590
|
? "Choose automatic or manual control for new sessions only; changing this does not alter the active session."
|
|
719
|
-
: "Choose the
|
|
591
|
+
: "Choose the profile for manual session starts; automatic sessions always start in Reasoning.";
|
|
720
592
|
const item =
|
|
721
593
|
options.scope === "local"
|
|
722
594
|
? {
|
|
@@ -760,7 +632,10 @@ function cognitiveRoutingSessionStartItem(options) {
|
|
|
760
632
|
item.displaySuffix = coreDisplaySuffix(item);
|
|
761
633
|
return item;
|
|
762
634
|
}
|
|
763
|
-
function
|
|
635
|
+
function isCognitiveRoutingRuntimeAvailable(pi) {
|
|
636
|
+
return isPiFlowHost(pi?.host) || supportsPiSessionModelStateApi(pi);
|
|
637
|
+
}
|
|
638
|
+
function freeflowItems(rawConfig, options = {}) {
|
|
764
639
|
const scope = options.scope ?? "repository";
|
|
765
640
|
const layers = options.layers;
|
|
766
641
|
const { localConfig, core, sources } = resolveSettingsCoreView(rawConfig, layers);
|
|
@@ -770,36 +645,12 @@ function freeflowItems(rawConfig, modeState, options = {}) {
|
|
|
770
645
|
localConfig,
|
|
771
646
|
id: "freeflow.enabled",
|
|
772
647
|
label: "Freeflow",
|
|
773
|
-
description: "Master switch for
|
|
648
|
+
description: "Master switch for Freeflow's core guidance, skills, and optional capabilities in this checkout.",
|
|
774
649
|
path: ["enabled"],
|
|
775
650
|
effectiveValue: core.enabled,
|
|
776
651
|
effectiveSource: sources.enabled,
|
|
777
652
|
defaultValue: DEFAULT_FREEFLOW_ENABLED,
|
|
778
653
|
});
|
|
779
|
-
const interactionItem = createScopedBooleanItem({
|
|
780
|
-
scope,
|
|
781
|
-
rawConfig,
|
|
782
|
-
localConfig,
|
|
783
|
-
id: "freeflow.interactionContract",
|
|
784
|
-
label: "Interaction Contract",
|
|
785
|
-
description: "Apply Freeflow's compact turn-interpretation and collaboration guidance.",
|
|
786
|
-
path: ["interactionContract"],
|
|
787
|
-
effectiveValue: core.interactionContract,
|
|
788
|
-
effectiveSource: sources.interactionContract,
|
|
789
|
-
defaultValue: DEFAULT_INTERACTION_CONTRACT_ENABLED,
|
|
790
|
-
});
|
|
791
|
-
const skillsItem = createScopedBooleanItem({
|
|
792
|
-
scope,
|
|
793
|
-
rawConfig,
|
|
794
|
-
localConfig,
|
|
795
|
-
id: "freeflow.skills.enabled",
|
|
796
|
-
label: "Skills",
|
|
797
|
-
description: "Expose Freeflow skills and discover Workflow before consequential or mutating work.",
|
|
798
|
-
path: ["skills", "enabled"],
|
|
799
|
-
effectiveValue: core.skills.enabled,
|
|
800
|
-
effectiveSource: sources.skillsEnabled,
|
|
801
|
-
defaultValue: DEFAULT_SKILLS_ENABLED,
|
|
802
|
-
});
|
|
803
654
|
const contextVirtualizationItem = createScopedBooleanItem({
|
|
804
655
|
scope,
|
|
805
656
|
rawConfig,
|
|
@@ -824,53 +675,11 @@ function freeflowItems(rawConfig, modeState, options = {}) {
|
|
|
824
675
|
effectiveSource: sources.conversationHistory,
|
|
825
676
|
defaultValue: DEFAULT_CONVERSATION_HISTORY_ENABLED,
|
|
826
677
|
});
|
|
827
|
-
const repositoryModeValue = validModeOrUndefined(rawConfig.defaultMode);
|
|
828
|
-
const repositoryDefaultMode = repositoryModeValue ?? "workflow";
|
|
829
|
-
const repositoryDefaultSource = repositoryModeValue ? "repository" : "builtin";
|
|
830
|
-
const localDefaultMode = validModeOrUndefined(localConfig.defaultMode);
|
|
831
|
-
const defaultModeItem = createScopedDefaultModeItem({
|
|
832
|
-
scope,
|
|
833
|
-
repositoryDefaultMode,
|
|
834
|
-
repositoryDefaultSource,
|
|
835
|
-
localDefaultMode,
|
|
836
|
-
effectiveValue: core.defaultMode,
|
|
837
|
-
effectiveSource: sources.defaultMode,
|
|
838
|
-
});
|
|
839
678
|
const freeflowInactive = !core.enabled;
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
skillsItem.inactive = freeflowInactive;
|
|
843
|
-
contextVirtualizationItem.inactive = freeflowInactive || !skillsEnabled;
|
|
844
|
-
conversationHistoryItem.inactive = freeflowInactive || !skillsEnabled;
|
|
845
|
-
defaultModeItem.inactive = freeflowInactive;
|
|
846
|
-
defaultModeItem.displaySuffix = coreDisplaySuffix(defaultModeItem, freeflowInactive || !skillsEnabled);
|
|
847
|
-
const sessionMode = modeState?.currentMode ?? "default";
|
|
848
|
-
const sessionModeItem = {
|
|
849
|
-
id: "freeflow.sessionMode",
|
|
850
|
-
label: "Session mode",
|
|
851
|
-
description:
|
|
852
|
-
"Temporary mode override for this Pi session. Use configured default clears the override without changing either config file.",
|
|
853
|
-
kind: "enum",
|
|
854
|
-
value: sessionMode,
|
|
855
|
-
values: ["default", ...MODE_VALUES],
|
|
856
|
-
valueLabels: {
|
|
857
|
-
...MODE_LABELS,
|
|
858
|
-
default: "Use configured default",
|
|
859
|
-
},
|
|
860
|
-
valueDescriptions: {
|
|
861
|
-
default: `${core.defaultMode} from ${sources.defaultMode}`,
|
|
862
|
-
...MODE_DESCRIPTIONS,
|
|
863
|
-
},
|
|
864
|
-
inactive: freeflowInactive || !skillsEnabled,
|
|
865
|
-
displaySuffix: sessionModeDisplaySuffix(
|
|
866
|
-
sessionMode,
|
|
867
|
-
core.defaultMode,
|
|
868
|
-
sources.defaultMode,
|
|
869
|
-
freeflowInactive || !skillsEnabled,
|
|
870
|
-
),
|
|
871
|
-
};
|
|
679
|
+
contextVirtualizationItem.inactive = freeflowInactive;
|
|
680
|
+
conversationHistoryItem.inactive = freeflowInactive;
|
|
872
681
|
const cognitiveRoutingState = options.cognitiveRouting;
|
|
873
|
-
const cognitiveRoutingRuntimeDisabled =
|
|
682
|
+
const cognitiveRoutingRuntimeDisabled = options.runtimeAvailable !== true;
|
|
874
683
|
const cognitiveRoutingGroup = (() => {
|
|
875
684
|
const cognitiveRoutingEnabledItem = createScopedBooleanItem({
|
|
876
685
|
scope,
|
|
@@ -879,14 +688,14 @@ function freeflowItems(rawConfig, modeState, options = {}) {
|
|
|
879
688
|
id: "freeflow.cognitiveRouting.enabled",
|
|
880
689
|
label: "Enabled",
|
|
881
690
|
description: cognitiveRoutingRuntimeDisabled
|
|
882
|
-
? "
|
|
691
|
+
? "Requires a host model-state control API; configuration is read-only on this host."
|
|
883
692
|
: "Allow Cognitive Routing to own the session model lease and switch the configured profiles.",
|
|
884
693
|
path: ["cognitiveRouting", "enabled"],
|
|
885
694
|
effectiveValue: cognitiveRoutingState?.enabled ?? false,
|
|
886
695
|
effectiveSource: cognitiveRoutingSettingsSource(cognitiveRoutingState?.enabledSource),
|
|
887
696
|
defaultValue: false,
|
|
888
697
|
});
|
|
889
|
-
cognitiveRoutingEnabledItem.inactive = freeflowInactive ||
|
|
698
|
+
cognitiveRoutingEnabledItem.inactive = freeflowInactive || cognitiveRoutingRuntimeDisabled;
|
|
890
699
|
cognitiveRoutingEnabledItem.runtimeInactive = cognitiveRoutingRuntimeDisabled;
|
|
891
700
|
const cognitiveRoutingProfiles = ["standard", "reasoning"].map((name) =>
|
|
892
701
|
cognitiveRoutingProfileItem({
|
|
@@ -908,11 +717,11 @@ function freeflowItems(rawConfig, modeState, options = {}) {
|
|
|
908
717
|
}),
|
|
909
718
|
);
|
|
910
719
|
for (const item of [...cognitiveRoutingProfiles, ...cognitiveRoutingSessionStart]) {
|
|
911
|
-
item.inactive ||= freeflowInactive ||
|
|
720
|
+
item.inactive ||= freeflowInactive || cognitiveRoutingRuntimeDisabled;
|
|
912
721
|
item.runtimeInactive = cognitiveRoutingRuntimeDisabled;
|
|
913
722
|
}
|
|
914
723
|
const cognitiveRoutingStatus = cognitiveRoutingRuntimeDisabled
|
|
915
|
-
? "
|
|
724
|
+
? "unavailable · host unsupported"
|
|
916
725
|
: cognitiveRoutingState
|
|
917
726
|
? cognitiveRoutingState.effective
|
|
918
727
|
? "active"
|
|
@@ -924,21 +733,17 @@ function freeflowItems(rawConfig, modeState, options = {}) {
|
|
|
924
733
|
id: "freeflow.cognitiveRouting",
|
|
925
734
|
label: "Cognitive Routing",
|
|
926
735
|
description: cognitiveRoutingRuntimeDisabled
|
|
927
|
-
? "Cognitive Routing configuration is visible for inspection but
|
|
928
|
-
: "Configure the
|
|
736
|
+
? "Cognitive Routing configuration is visible for inspection but requires a host model-state control API."
|
|
737
|
+
: "Configure the Standard and Reasoning profiles and choose whether Freeflow may manage model state for this repository.",
|
|
929
738
|
kind: "group",
|
|
930
739
|
value: cognitiveRoutingRuntimeDisabled ? false : (cognitiveRoutingState?.enabled ?? false),
|
|
931
|
-
inactive: freeflowInactive
|
|
740
|
+
inactive: freeflowInactive,
|
|
932
741
|
displaySuffix: cognitiveRoutingStatus,
|
|
933
742
|
children: [cognitiveRoutingEnabledItem, ...cognitiveRoutingProfiles, ...cognitiveRoutingSessionStart],
|
|
934
743
|
};
|
|
935
744
|
})();
|
|
936
745
|
return [
|
|
937
746
|
freeflowItem,
|
|
938
|
-
interactionItem,
|
|
939
|
-
skillsItem,
|
|
940
|
-
sessionModeItem,
|
|
941
|
-
defaultModeItem,
|
|
942
747
|
...(cognitiveRoutingGroup ? [cognitiveRoutingGroup] : []),
|
|
943
748
|
{
|
|
944
749
|
id: "freeflow.context",
|
|
@@ -954,8 +759,7 @@ function freeflowItems(rawConfig, modeState, options = {}) {
|
|
|
954
759
|
function pruneKnownDefaults(config) {
|
|
955
760
|
const defaultPaths = [
|
|
956
761
|
{ path: ["enabled"], value: DEFAULT_FREEFLOW_ENABLED },
|
|
957
|
-
{ path: ["
|
|
958
|
-
{ path: ["skills", "enabled"], value: DEFAULT_SKILLS_ENABLED },
|
|
762
|
+
{ path: ["contextVirtualization"], value: DEFAULT_CONTEXT_VIRTUALIZATION_ENABLED },
|
|
959
763
|
{ path: ["conversationHistory"], value: DEFAULT_CONVERSATION_HISTORY_ENABLED },
|
|
960
764
|
];
|
|
961
765
|
for (const item of defaultPaths) {
|
|
@@ -1068,33 +872,12 @@ function findSettingsItem(items, id) {
|
|
|
1068
872
|
function refreshSettingsDerivedState(items) {
|
|
1069
873
|
const freeflowItem = findSettingsItem(items, "freeflow.enabled");
|
|
1070
874
|
const freeflowInactive = freeflowItem ? effectiveItemValue(freeflowItem) !== true : false;
|
|
1071
|
-
const skillsItem = findSettingsItem(items, "freeflow.skills.enabled");
|
|
1072
|
-
const skillsEnabled = skillsItem ? effectiveItemValue(skillsItem) === true : true;
|
|
1073
|
-
const sessionModeItem = findSettingsItem(items, "freeflow.sessionMode");
|
|
1074
|
-
const defaultModeItem = findSettingsItem(items, "freeflow.defaultMode");
|
|
1075
875
|
const cognitiveRoutingGroup = findSettingsItem(items, "freeflow.cognitiveRouting");
|
|
1076
876
|
const cognitiveRoutingEnabledItem = findSettingsItem(items, "freeflow.cognitiveRouting.enabled");
|
|
1077
877
|
const cognitiveRoutingProfiles = [
|
|
1078
878
|
findSettingsItem(items, "freeflow.cognitiveRouting.standard"),
|
|
1079
879
|
findSettingsItem(items, "freeflow.cognitiveRouting.reasoning"),
|
|
1080
880
|
];
|
|
1081
|
-
if (sessionModeItem) {
|
|
1082
|
-
const defaultMode = String(
|
|
1083
|
-
defaultModeItem ? effectiveItemValue(defaultModeItem) : (sessionModeItem.inheritedValue ?? "workflow"),
|
|
1084
|
-
);
|
|
1085
|
-
const defaultSource = defaultModeItem?.effectiveSource ?? sessionModeItem.inheritedSource ?? "builtin";
|
|
1086
|
-
sessionModeItem.inactive = freeflowInactive || !skillsEnabled;
|
|
1087
|
-
sessionModeItem.displaySuffix = sessionModeDisplaySuffix(
|
|
1088
|
-
String(sessionModeItem.value),
|
|
1089
|
-
defaultMode,
|
|
1090
|
-
defaultSource,
|
|
1091
|
-
freeflowInactive || !skillsEnabled,
|
|
1092
|
-
);
|
|
1093
|
-
sessionModeItem.valueDescriptions = {
|
|
1094
|
-
default: `${defaultMode} from ${defaultSource}`,
|
|
1095
|
-
...MODE_DESCRIPTIONS,
|
|
1096
|
-
};
|
|
1097
|
-
}
|
|
1098
881
|
if (cognitiveRoutingGroup && cognitiveRoutingEnabledItem) {
|
|
1099
882
|
const enabled = effectiveItemValue(cognitiveRoutingEnabledItem) === true;
|
|
1100
883
|
const profilesConfigured = cognitiveRoutingProfiles.every((item) =>
|
|
@@ -1108,7 +891,7 @@ function refreshSettingsDerivedState(items) {
|
|
|
1108
891
|
: "configured"
|
|
1109
892
|
: "not configured"
|
|
1110
893
|
: "disabled";
|
|
1111
|
-
cognitiveRoutingGroup.inactive = freeflowInactive
|
|
894
|
+
cognitiveRoutingGroup.inactive = freeflowInactive;
|
|
1112
895
|
}
|
|
1113
896
|
const contextGroup = findSettingsItem(items, "freeflow.context");
|
|
1114
897
|
if (contextGroup?.children?.length) {
|
|
@@ -1121,31 +904,11 @@ function refreshSettingsDerivedState(items) {
|
|
|
1121
904
|
candidate.inactive = false;
|
|
1122
905
|
} else if (candidate.configScope) {
|
|
1123
906
|
const inactive =
|
|
1124
|
-
candidate.id === "freeflow.enabled"
|
|
1125
|
-
? false
|
|
1126
|
-
: candidate.runtimeInactive === true ||
|
|
1127
|
-
freeflowInactive ||
|
|
1128
|
-
(!skillsEnabled &&
|
|
1129
|
-
[
|
|
1130
|
-
"freeflow.cognitiveRouting",
|
|
1131
|
-
"freeflow.cognitiveRouting.enabled",
|
|
1132
|
-
"freeflow.cognitiveRouting.standard",
|
|
1133
|
-
"freeflow.cognitiveRouting.reasoning",
|
|
1134
|
-
"freeflow.cognitiveRouting.sessionStart.control",
|
|
1135
|
-
"freeflow.cognitiveRouting.sessionStart.profile",
|
|
1136
|
-
"freeflow.contextVirtualization",
|
|
1137
|
-
"freeflow.conversationHistory",
|
|
1138
|
-
].includes(candidate.id));
|
|
1139
|
-
const displayInactive = candidate.id === "freeflow.defaultMode" ? freeflowInactive || !skillsEnabled : inactive;
|
|
907
|
+
candidate.id === "freeflow.enabled" ? false : candidate.runtimeInactive === true || freeflowInactive;
|
|
1140
908
|
candidate.inactive = inactive;
|
|
1141
|
-
candidate.displaySuffix = coreDisplaySuffix(candidate,
|
|
1142
|
-
} else if (candidate.id === "freeflow.sessionMode") {
|
|
1143
|
-
candidate.inactive = candidate.runtimeInactive === true || freeflowInactive || !skillsEnabled;
|
|
909
|
+
candidate.displaySuffix = coreDisplaySuffix(candidate, inactive);
|
|
1144
910
|
} else {
|
|
1145
|
-
candidate.inactive =
|
|
1146
|
-
candidate.runtimeInactive === true ||
|
|
1147
|
-
freeflowInactive ||
|
|
1148
|
-
(!skillsEnabled && candidate.id === "freeflow.cognitiveRouting");
|
|
911
|
+
candidate.inactive = candidate.runtimeInactive === true || freeflowInactive;
|
|
1149
912
|
}
|
|
1150
913
|
});
|
|
1151
914
|
}
|
|
@@ -1251,7 +1014,7 @@ function freeflowStatusText(state, cognitiveRoutingController) {
|
|
|
1251
1014
|
const cognitiveRouting = state.cognitiveRouting;
|
|
1252
1015
|
const cognitiveRoutingStatus = cognitiveRouting
|
|
1253
1016
|
? cognitiveRouting.blockingReason?.code === "runtime_disabled"
|
|
1254
|
-
? "
|
|
1017
|
+
? "unavailable (host unsupported)"
|
|
1255
1018
|
: cognitiveRouting.effective
|
|
1256
1019
|
? routingState?.effective
|
|
1257
1020
|
? `active (${routingState.activeProfile ?? "unknown"}, ${routingState.controlMode})`
|
|
@@ -1263,16 +1026,12 @@ function freeflowStatusText(state, cognitiveRoutingController) {
|
|
|
1263
1026
|
const contextEnabled = state.contextVirtualization?.effective || state.conversationHistory?.effective;
|
|
1264
1027
|
return [
|
|
1265
1028
|
`Freeflow: ${state.enabled ? "enabled" : "disabled"}${sessionSuffix(state.configSources.enabled)}`,
|
|
1266
|
-
`interaction contract: ${state.interactionContract.effective ? "enabled" : "disabled"}${sessionSuffix(state.configSources.interactionContract)}`,
|
|
1267
|
-
`skills: ${state.skills.effective ? "enabled" : "disabled (workflow modes inactive)"}${sessionSuffix(state.configSources.skillsEnabled)}`,
|
|
1268
1029
|
`context: ${contextEnabled ? "enabled" : "disabled"} (virtualization ${state.contextVirtualization?.effective ? "enabled" : "disabled"}, history ${state.conversationHistory?.effective ? "enabled" : "disabled"})`,
|
|
1269
1030
|
...(cognitiveRoutingStatus ? [`cognitive routing: ${cognitiveRoutingStatus}`] : []),
|
|
1270
1031
|
].join("; ");
|
|
1271
1032
|
}
|
|
1272
1033
|
const NON_TUI_SETTINGS_GUIDANCE =
|
|
1273
|
-
"Freeflow settings require Pi TUI mode. Use /freeflow status to inspect current state; supported non-TUI changes are /freeflow enable
|
|
1274
|
-
const NON_TUI_MODE_GUIDANCE =
|
|
1275
|
-
"Freeflow mode selector requires Pi TUI mode. Use /freeflow mode conversation, /freeflow mode workflow, /freeflow mode strict-workflow, or /freeflow mode reset.";
|
|
1034
|
+
"Freeflow settings require Pi TUI mode. Use /freeflow status to inspect current state; supported non-TUI changes are /freeflow enable and /freeflow disable.";
|
|
1276
1035
|
function ensureSettingsIdle(ctx) {
|
|
1277
1036
|
if (typeof ctx?.isIdle !== "function" || ctx.isIdle()) return true;
|
|
1278
1037
|
ctx.ui?.notify?.("Freeflow settings and profile changes are available only while Pi is idle.", "warning");
|
|
@@ -1323,19 +1082,15 @@ export async function handleFreeflowCommand(args, ctx, afterChange, pi, cognitiv
|
|
|
1323
1082
|
const [action, ...rest] = input.split(/\s+/);
|
|
1324
1083
|
const actionValue = rest.join(" ");
|
|
1325
1084
|
const nonTui = ctx?.mode && ctx.mode !== "tui";
|
|
1326
|
-
if (nonTui && action === "mode" && !actionValue) {
|
|
1327
|
-
return nonTuiGuidance(ctx, NON_TUI_MODE_GUIDANCE);
|
|
1328
|
-
}
|
|
1329
1085
|
const settingsSelector =
|
|
1330
1086
|
action === "settings" &&
|
|
1331
1087
|
(!actionValue || ["session", "local", "personal", "repo", "repository", "shared"].includes(actionValue));
|
|
1332
1088
|
if (nonTui && settingsSelector) {
|
|
1333
1089
|
return nonTuiGuidance(ctx, NON_TUI_SETTINGS_GUIDANCE);
|
|
1334
1090
|
}
|
|
1335
|
-
const [layers, state
|
|
1091
|
+
const [layers, state] = await Promise.all([
|
|
1336
1092
|
readFreeflowConfigLayers(ctx.cwd),
|
|
1337
1093
|
readCapabilityState(ctx.cwd, ctx, pi?.host),
|
|
1338
|
-
readModeState(ctx.cwd),
|
|
1339
1094
|
]);
|
|
1340
1095
|
const configState = layers.repository;
|
|
1341
1096
|
const raw = configState.valid ? configState.parsed : {};
|
|
@@ -1354,48 +1109,15 @@ export async function handleFreeflowCommand(args, ctx, afterChange, pi, cognitiv
|
|
|
1354
1109
|
);
|
|
1355
1110
|
return { changed: false, reloaded: false, error: "invalid_local_config" };
|
|
1356
1111
|
}
|
|
1357
|
-
if (action === "mode") {
|
|
1358
|
-
if (!ensureSettingsIdle(ctx)) return { changed: false, reloaded: false, error: "busy" };
|
|
1359
|
-
if (actionValue) {
|
|
1360
|
-
const result = await handleModeCommand(actionValue, ctx, pi);
|
|
1361
|
-
return { changed: result.changed, reloaded: false, error: result.error };
|
|
1362
|
-
}
|
|
1363
|
-
if (!state.enabled || !state.skills.effective) {
|
|
1364
|
-
const result = await handleModeCommand(undefined, ctx, pi);
|
|
1365
|
-
return { changed: false, reloaded: false, error: result.error };
|
|
1366
|
-
}
|
|
1367
|
-
if (typeof ctx?.ui?.custom !== "function") {
|
|
1368
|
-
const result = await handleModeCommand(undefined, ctx, pi);
|
|
1369
|
-
return { changed: false, reloaded: false, error: result.error };
|
|
1370
|
-
}
|
|
1371
|
-
const item = freeflowItems(raw, modeState, {
|
|
1372
|
-
scope: "local",
|
|
1373
|
-
layers,
|
|
1374
|
-
cognitiveRouting: state.cognitiveRouting,
|
|
1375
|
-
ctx,
|
|
1376
|
-
hostInfo: pi?.host,
|
|
1377
|
-
}).find((candidate) => candidate.id === "freeflow.sessionMode");
|
|
1378
|
-
const session = await openSettings({
|
|
1379
|
-
title: "Freeflow Mode",
|
|
1380
|
-
items: [item],
|
|
1381
|
-
initialChoice: item,
|
|
1382
|
-
ctx,
|
|
1383
|
-
onChange: async (_item, value) => {
|
|
1384
|
-
const result = await handleModeCommand(String(value), ctx, pi);
|
|
1385
|
-
return { changed: result.changed, reloadRequired: false };
|
|
1386
|
-
},
|
|
1387
|
-
});
|
|
1388
|
-
return { changed: session.changed, reloaded: false, error: session.failed ? "write_failed" : undefined };
|
|
1389
|
-
}
|
|
1390
1112
|
if (["enable", "on", "true", "disable", "off", "false"].includes(action)) {
|
|
1391
1113
|
if (!ensureSettingsIdle(ctx)) return { changed: false, reloaded: false, error: "busy" };
|
|
1392
1114
|
const enabled = ["enable", "on", "true"].includes(action);
|
|
1393
|
-
const item = freeflowItems(raw,
|
|
1115
|
+
const item = freeflowItems(raw, {
|
|
1394
1116
|
scope: "repository",
|
|
1395
1117
|
layers,
|
|
1396
1118
|
cognitiveRouting: state.cognitiveRouting,
|
|
1397
1119
|
ctx,
|
|
1398
|
-
|
|
1120
|
+
runtimeAvailable: isCognitiveRoutingRuntimeAvailable(pi),
|
|
1399
1121
|
}).find((candidate) => candidate.id === "freeflow.enabled");
|
|
1400
1122
|
await updateConfig(ctx.cwd, item, enabled, "repository");
|
|
1401
1123
|
await afterChange(true);
|
|
@@ -1409,7 +1131,7 @@ export async function handleFreeflowCommand(args, ctx, afterChange, pi, cognitiv
|
|
|
1409
1131
|
}
|
|
1410
1132
|
if (action && action !== "settings") {
|
|
1411
1133
|
ctx.ui.notify(
|
|
1412
|
-
"Usage: /freeflow, /freeflow settings [local|repo], /freeflow status, /freeflow
|
|
1134
|
+
"Usage: /freeflow, /freeflow settings [local|repo], /freeflow status, /freeflow enable, or /freeflow disable",
|
|
1413
1135
|
"warning",
|
|
1414
1136
|
);
|
|
1415
1137
|
return { changed: false, reloaded: false, error: "invalid_action" };
|
|
@@ -1430,13 +1152,13 @@ export async function handleFreeflowCommand(args, ctx, afterChange, pi, cognitiv
|
|
|
1430
1152
|
let reconcileCognitiveRouting = settingsScope === "session";
|
|
1431
1153
|
const items =
|
|
1432
1154
|
settingsScope === "session"
|
|
1433
|
-
? sessionFreeflowItems(state,
|
|
1434
|
-
: freeflowItems(raw,
|
|
1155
|
+
? sessionFreeflowItems(state, cognitiveRoutingController)
|
|
1156
|
+
: freeflowItems(raw, {
|
|
1435
1157
|
scope: settingsScope,
|
|
1436
1158
|
layers,
|
|
1437
1159
|
cognitiveRouting: state.cognitiveRouting,
|
|
1438
1160
|
ctx,
|
|
1439
|
-
|
|
1161
|
+
runtimeAvailable: isCognitiveRoutingRuntimeAvailable(pi),
|
|
1440
1162
|
});
|
|
1441
1163
|
const session = await openSettings({
|
|
1442
1164
|
title:
|
|
@@ -1449,14 +1171,10 @@ export async function handleFreeflowCommand(args, ctx, afterChange, pi, cognitiv
|
|
|
1449
1171
|
ctx,
|
|
1450
1172
|
onChange: async (item, value) => {
|
|
1451
1173
|
if (!ensureSettingsIdle(ctx)) return { changed: false, reloadRequired: false };
|
|
1452
|
-
if (!
|
|
1453
|
-
ctx.ui.notify("Cognitive Routing is
|
|
1174
|
+
if (!isCognitiveRoutingRuntimeAvailable(pi) && item.id.startsWith("freeflow.cognitiveRouting.")) {
|
|
1175
|
+
ctx.ui.notify("Cognitive Routing is unavailable because this host lacks model-state controls.", "warning");
|
|
1454
1176
|
return { changed: false, reloadRequired: false };
|
|
1455
1177
|
}
|
|
1456
|
-
if (item.id === "freeflow.sessionMode") {
|
|
1457
|
-
const result = await handleModeCommand(String(value), ctx, pi);
|
|
1458
|
-
return { changed: result.changed, reloadRequired: false };
|
|
1459
|
-
}
|
|
1460
1178
|
if (item.id === "freeflow.cognitiveRouting.profile") {
|
|
1461
1179
|
if (!cognitiveRoutingController) {
|
|
1462
1180
|
ctx.ui.notify("Cognitive Routing is unavailable for this session.", "warning");
|
|
@@ -1483,8 +1201,6 @@ export async function handleFreeflowCommand(args, ctx, afterChange, pi, cognitiv
|
|
|
1483
1201
|
if (item.configScope === "session") {
|
|
1484
1202
|
const keyById = {
|
|
1485
1203
|
"freeflow.enabled": "enabled",
|
|
1486
|
-
"freeflow.interactionContract": "interactionContract",
|
|
1487
|
-
"freeflow.skills.enabled": "skillsEnabled",
|
|
1488
1204
|
"freeflow.contextVirtualization": "contextVirtualization",
|
|
1489
1205
|
"freeflow.conversationHistory": "conversationHistory",
|
|
1490
1206
|
};
|