@hassangameryt/freeflow 0.4.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.
- package/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +2 -1
- package/.codex-plugin/plugin.json +2 -1
- package/README.md +150 -155
- package/capabilities/cognitive-routing/SKILL.md +229 -0
- package/capabilities/context-virtualization/SKILL.md +103 -0
- package/capabilities/conversation-history/SKILL.md +53 -0
- package/command-surface.json +17 -13
- package/hooks/freeflow-runtime-context.mjs +393 -159
- package/hooks/hooks.json +26 -1
- package/hooks/tests/check-runtime-context-hook.sh +223 -54
- package/package.json +25 -16
- package/pi-extension/dist/cognitive-routing/commands.js +96 -0
- package/pi-extension/dist/cognitive-routing/config.js +236 -0
- package/pi-extension/dist/cognitive-routing/controller.js +862 -0
- package/pi-extension/dist/cognitive-routing/history.js +439 -0
- package/pi-extension/dist/cognitive-routing/host.js +126 -0
- package/pi-extension/dist/cognitive-routing/runtime.js +43 -0
- package/pi-extension/dist/cognitive-routing/tool.js +211 -0
- package/pi-extension/dist/cognitive-routing/types.js +6 -0
- package/pi-extension/dist/context-virtualization/commands.js +89 -0
- package/pi-extension/dist/context-virtualization/projector.js +42 -0
- package/pi-extension/dist/context-virtualization/runtime.js +356 -0
- package/pi-extension/dist/context-virtualization/state.js +57 -0
- package/pi-extension/dist/context-virtualization/types.js +10 -0
- package/pi-extension/dist/conversation-history/passages.js +66 -0
- package/pi-extension/dist/conversation-history/ranking.js +105 -0
- package/pi-extension/dist/conversation-history/runtime.js +226 -0
- package/pi-extension/dist/conversation-history/search.js +56 -0
- package/pi-extension/dist/conversation-history/types.js +1 -0
- package/pi-extension/dist/freeflow-context/resolver.js +120 -0
- package/pi-extension/dist/freeflow-context/runtime.js +80 -0
- package/pi-extension/dist/freeflow-context/source-projector.js +95 -0
- package/pi-extension/dist/freeflow-context/tool.js +308 -0
- package/pi-extension/dist/freeflow-context/types.js +12 -0
- package/pi-extension/dist/freeflow-context/visibility.js +28 -0
- package/pi-extension/dist/index.js +516 -98
- package/pi-extension/dist/runtime/runtime-context.js +318 -271
- package/pi-extension/dist/runtime/runtime-identity.js +5 -0
- package/pi-extension/dist/settings/settings-tui.js +78 -0
- package/pi-extension/dist/settings/settings-ui.js +593 -563
- package/pi-extension/dist/ui/text-component.js +57 -0
- package/pi-extension/src/cognitive-routing/commands.ts +119 -0
- package/pi-extension/src/cognitive-routing/config.ts +307 -0
- package/pi-extension/src/cognitive-routing/controller.ts +1118 -0
- package/pi-extension/src/cognitive-routing/history.ts +638 -0
- package/pi-extension/src/cognitive-routing/host.ts +172 -0
- package/pi-extension/src/cognitive-routing/runtime.ts +57 -0
- package/pi-extension/src/cognitive-routing/tool.ts +272 -0
- package/pi-extension/src/cognitive-routing/types.ts +89 -0
- package/pi-extension/src/context-virtualization/commands.ts +111 -0
- package/pi-extension/src/context-virtualization/projector.ts +62 -0
- package/pi-extension/src/context-virtualization/runtime.ts +406 -0
- package/pi-extension/src/context-virtualization/state.ts +79 -0
- package/pi-extension/src/context-virtualization/types.ts +92 -0
- package/pi-extension/src/conversation-history/passages.ts +81 -0
- package/pi-extension/src/conversation-history/ranking.ts +155 -0
- package/pi-extension/src/conversation-history/runtime.ts +250 -0
- package/pi-extension/src/conversation-history/search.ts +79 -0
- package/pi-extension/src/conversation-history/types.ts +31 -0
- package/pi-extension/src/freeflow-context/resolver.ts +139 -0
- package/pi-extension/src/freeflow-context/runtime.ts +100 -0
- package/pi-extension/src/freeflow-context/source-projector.ts +106 -0
- package/pi-extension/src/freeflow-context/tool.ts +360 -0
- package/pi-extension/src/freeflow-context/types.ts +70 -0
- package/pi-extension/src/freeflow-context/visibility.ts +53 -0
- package/pi-extension/src/index.ts +553 -101
- package/pi-extension/src/runtime/runtime-context.ts +339 -281
- package/pi-extension/src/runtime/runtime-identity.ts +8 -0
- package/pi-extension/src/settings/settings-tui.ts +93 -0
- package/pi-extension/src/settings/settings-ui.ts +700 -613
- package/pi-extension/src/ui/text-component.ts +66 -0
- package/pi-extension/tests/cognitive-routing/commands.test.js +134 -0
- package/pi-extension/tests/cognitive-routing/controller.test.js +1099 -0
- package/pi-extension/tests/cognitive-routing/extension-lifecycle.test.js +1071 -0
- package/pi-extension/tests/cognitive-routing/history.test.js +274 -0
- package/pi-extension/tests/cognitive-routing/host-fixture.js +4 -0
- package/pi-extension/tests/cognitive-routing/host-identity.test.js +63 -0
- package/pi-extension/tests/cognitive-routing/profile-resolution.test.js +236 -0
- package/pi-extension/tests/cognitive-routing/tool.test.js +230 -0
- package/pi-extension/tests/context-virtualization/extension.test.js +749 -0
- package/pi-extension/tests/context-virtualization/projector.test.js +110 -0
- package/pi-extension/tests/context-virtualization/runtime.test.js +216 -0
- package/pi-extension/tests/conversation-history/runtime.test.js +98 -0
- package/pi-extension/tests/conversation-history/search.test.js +97 -0
- package/pi-extension/tests/integration/pi-extension.test.js +928 -2047
- package/pi-extension/tests/integration/prompt-architecture.test.js +305 -0
- package/runtime/prompts/cognitive-routing.md +9 -0
- package/runtime/prompts/context-virtualization.md +3 -0
- package/runtime/prompts/conversation-history.md +3 -0
- package/runtime/prompts/core.md +13 -0
- package/runtime/prompts/interaction-contract.md +7 -0
- package/runtime/prompts/skills.md +65 -0
- package/skills/action-selection/SKILL.md +91 -0
- package/skills/bypass/SKILL.md +3 -2
- package/skills/commit-work/SKILL.md +1 -1
- package/skills/commit-work/references/staging-decisions.md +1 -1
- package/skills/decision-gate/SKILL.md +1 -1
- package/skills/design-for-depth/SKILL.md +14 -33
- package/skills/design-for-depth/references/design-pressure-signals.md +1 -1
- package/skills/design-for-depth/references/interface-design-loop.md +1 -1
- package/skills/design-for-depth/references/software-design-philosophy.md +1 -1
- package/skills/diagnose-failure/SKILL.md +20 -14
- package/skills/diagnose-failure/references/diagnostic-loop-catalog.md +1 -3
- package/skills/diagnose-failure/references/{flaky-and-performance.md → flaky-and-performance-diagnosis.md} +1 -1
- package/skills/discuss/SKILL.md +34 -22
- package/skills/discuss/references/discussion-continuity.md +71 -0
- package/skills/evaluate-skill/SKILL.md +5 -5
- package/skills/evaluate-skill/references/{definition-schema.md → evaluation-definition-schema.md} +42 -2
- package/skills/evaluate-skill/references/execution-and-evidence.md +8 -3
- package/skills/evaluate-skill/scripts/lib/definitions.mjs +114 -3
- package/skills/evaluate-skill/scripts/lib/grade-interaction.mjs +156 -1
- package/skills/evaluate-skill/scripts/lib/grade.mjs +9 -1
- package/skills/evaluate-skill/scripts/lib/pi.mjs +147 -32
- package/skills/evaluate-skill/scripts/lib/rpc.mjs +4 -4
- package/skills/evaluate-skill/scripts/lib/runner.mjs +36 -14
- package/skills/evaluate-skill/scripts/lib/sandbox.mjs +92 -0
- package/skills/evaluate-skill/scripts/pi-guard.mjs +1 -1
- package/skills/evaluate-skill/scripts/pi-observer.mjs +66 -0
- package/skills/evaluate-skill/scripts/skill-eval.mjs +6 -5
- package/skills/execute-work/SKILL.md +18 -15
- package/skills/execute-work/references/code-practices.md +1 -1
- package/skills/execute-work/references/execute-work-edges.md +42 -0
- package/skills/finish-branch/SKILL.md +2 -2
- package/skills/finish-branch/references/integration-options.md +1 -1
- package/skills/handoff/SKILL.md +3 -3
- package/skills/launch-work/SKILL.md +1 -1
- package/skills/launch-work/references/launch-readiness.md +2 -2
- package/skills/migration-work/SKILL.md +2 -2
- package/skills/migration-work/references/migration-lifecycle.md +1 -1
- package/skills/mode-contract/SKILL.md +32 -10
- package/skills/release-work/SKILL.md +1 -1
- package/skills/release-work/references/release-evidence.md +1 -1
- package/skills/review-artifact/SKILL.md +28 -26
- package/skills/review-work/SKILL.md +28 -26
- package/skills/review-work/references/{reviewer-prompt.md → independent-work-reviewer-contract.md} +1 -1
- package/skills/review-work/references/security-risk-lens.md +1 -1
- package/skills/setup-freeflow/SKILL.md +6 -10
- package/skills/setup-freeflow/references/activation-contract.md +5 -10
- package/skills/setup-freeflow/references/host-setup.md +3 -7
- package/skills/simplify-code/SKILL.md +1 -1
- package/skills/simplify-code/references/simplification-patterns.md +1 -1
- package/skills/tdd/SKILL.md +18 -38
- package/skills/tdd/references/test-design.md +2 -2
- package/skills/track-work/SKILL.md +362 -58
- package/skills/track-work/scripts/lib/codec.mjs +570 -0
- package/skills/track-work/scripts/lib/commands.mjs +568 -0
- package/skills/track-work/scripts/lib/contract.mjs +303 -0
- package/skills/track-work/scripts/lib/model.mjs +506 -0
- package/skills/track-work/scripts/lib/operations.mjs +965 -0
- package/skills/track-work/scripts/lib/record-store.mjs +264 -0
- package/skills/track-work/scripts/lib/result.mjs +37 -0
- package/skills/track-work/scripts/lib/rewrites.mjs +740 -0
- package/skills/track-work/scripts/lib/schema.mjs +277 -0
- package/skills/track-work/scripts/lib/source-inventory.mjs +162 -0
- package/skills/track-work/scripts/lib/views.mjs +443 -0
- package/skills/track-work/scripts/lib/workspace.mjs +134 -0
- package/skills/track-work/scripts/working-record.mjs +122 -0
- package/skills/verify-work/SKILL.md +14 -2
- package/skills/verify-work/references/browser-runtime-evidence.md +1 -1
- package/skills/verify-work/references/integration-evidence.md +1 -1
- package/skills/verify-work/references/performance-evidence.md +1 -1
- package/skills/workflow/SKILL.md +105 -53
- package/skills/workflow/references/domain-skill-composition.md +22 -42
- package/skills/write-plan/SKILL.md +1 -1
- package/skills/write-skill/SKILL.md +3 -2
- package/skills/write-skill/references/progressive-disclosure.md +17 -3
- package/pi-extension/dist/output-router/host-producer-identification.js +0 -232
- package/pi-extension/dist/output-router/native-safety-net.js +0 -216
- package/pi-extension/dist/output-router/observed-tool-routing.js +0 -122
- package/pi-extension/dist/output-router/renderers.js +0 -1023
- package/pi-extension/dist/output-router/router-tools.js +0 -554
- package/pi-extension/dist/output-router/schemas.js +0 -383
- package/pi-extension/dist/output-router/status.js +0 -744
- package/pi-extension/dist/output-router/utils.js +0 -502
- package/pi-extension/src/output-router/host-producer-identification.ts +0 -256
- package/pi-extension/src/output-router/native-safety-net.ts +0 -248
- package/pi-extension/src/output-router/observed-tool-routing.ts +0 -134
- package/pi-extension/src/output-router/renderers.ts +0 -1108
- package/pi-extension/src/output-router/router-tools.ts +0 -579
- package/pi-extension/src/output-router/schemas.ts +0 -387
- package/pi-extension/src/output-router/status.ts +0 -791
- package/pi-extension/src/output-router/utils.ts +0 -554
- package/pi-extension/tests/output-router/observed-producers.test.js +0 -132
- package/pi-extension/tests/output-router/search.test.js +0 -722
- package/router/dist/benchmarks/benchmark-harness.d.ts +0 -35
- package/router/dist/benchmarks/benchmark-harness.js +0 -92
- package/router/dist/benchmarks/benchmarks.d.ts +0 -109
- package/router/dist/benchmarks/benchmarks.js +0 -979
- package/router/dist/benchmarks/codex-qa-benchmarks.d.ts +0 -95
- package/router/dist/benchmarks/codex-qa-benchmarks.js +0 -500
- package/router/dist/benchmarks/command-benchmarks.d.ts +0 -143
- package/router/dist/benchmarks/command-benchmarks.js +0 -698
- package/router/dist/benchmarks/context-mode-normalized-benchmarks.d.ts +0 -82
- package/router/dist/benchmarks/context-mode-normalized-benchmarks.js +0 -773
- package/router/dist/benchmarks/context-mode-real-deep-benchmark.d.ts +0 -132
- package/router/dist/benchmarks/context-mode-real-deep-benchmark.js +0 -1380
- package/router/dist/benchmarks/context-saving-baseline.d.ts +0 -60
- package/router/dist/benchmarks/context-saving-baseline.js +0 -470
- package/router/dist/benchmarks/index-benchmarks.d.ts +0 -103
- package/router/dist/benchmarks/index-benchmarks.js +0 -862
- package/router/dist/benchmarks/storage-policy-benchmarks.d.ts +0 -101
- package/router/dist/benchmarks/storage-policy-benchmarks.js +0 -618
- package/router/dist/benchmarks/vault-index-benchmarks.d.ts +0 -56
- package/router/dist/benchmarks/vault-index-benchmarks.js +0 -322
- package/router/dist/config/config.d.ts +0 -103
- package/router/dist/config/config.js +0 -632
- package/router/dist/config/router-contract.d.ts +0 -10
- package/router/dist/config/router-contract.js +0 -54
- package/router/dist/config/schema.d.ts +0 -27
- package/router/dist/config/schema.js +0 -648
- package/router/dist/config/types.d.ts +0 -573
- package/router/dist/config/types.js +0 -41
- package/router/dist/evidence/bounded-evidence.d.ts +0 -40
- package/router/dist/evidence/bounded-evidence.js +0 -323
- package/router/dist/evidence/evidence-range-selector.d.ts +0 -24
- package/router/dist/evidence/evidence-range-selector.js +0 -232
- package/router/dist/evidence/evidence-search.d.ts +0 -27
- package/router/dist/evidence/evidence-search.js +0 -490
- package/router/dist/evidence/evidence.d.ts +0 -38
- package/router/dist/evidence/evidence.js +0 -200
- package/router/dist/evidence/failure-contracts.d.ts +0 -37
- package/router/dist/evidence/failure-contracts.js +0 -166
- package/router/dist/evidence/line-ranges.d.ts +0 -24
- package/router/dist/evidence/line-ranges.js +0 -22
- package/router/dist/experiments/local-index.d.ts +0 -64
- package/router/dist/experiments/local-index.js +0 -581
- package/router/dist/index.d.ts +0 -30
- package/router/dist/index.js +0 -32
- package/router/dist/local/local-traversal.d.ts +0 -18
- package/router/dist/local/local-traversal.js +0 -334
- package/router/dist/processing/engine.d.ts +0 -132
- package/router/dist/processing/engine.js +0 -533
- package/router/dist/processing/reducers.d.ts +0 -280
- package/router/dist/processing/reducers.js +0 -1673
- package/router/dist/processing/renderers.d.ts +0 -31
- package/router/dist/processing/renderers.js +0 -195
- package/router/dist/processing/scripts.d.ts +0 -91
- package/router/dist/processing/scripts.js +0 -386
- package/router/dist/repo/repo-traversal.d.ts +0 -18
- package/router/dist/repo/repo-traversal.js +0 -245
- package/router/dist/routing/observed-reducers.d.ts +0 -41
- package/router/dist/routing/observed-reducers.js +0 -661
- package/router/dist/routing/observed-routing.d.ts +0 -26
- package/router/dist/routing/observed-routing.js +0 -378
- package/router/dist/routing/parsers.d.ts +0 -16
- package/router/dist/routing/parsers.js +0 -521
- package/router/dist/routing/run-filters.d.ts +0 -60
- package/router/dist/routing/run-filters.js +0 -238
- package/router/dist/routing/run-reducers.d.ts +0 -49
- package/router/dist/routing/run-reducers.js +0 -122
- package/router/dist/sandbox/adapter-roots.d.ts +0 -46
- package/router/dist/sandbox/adapter-roots.js +0 -66
- package/router/dist/sandbox/eryx-python-adapter.d.ts +0 -13
- package/router/dist/sandbox/eryx-python-adapter.js +0 -868
- package/router/dist/sandbox/jq-wasm-adapter.d.ts +0 -9
- package/router/dist/sandbox/jq-wasm-adapter.js +0 -429
- package/router/dist/sandbox/quickjs-wasi-adapter.d.ts +0 -13
- package/router/dist/sandbox/quickjs-wasi-adapter.js +0 -384
- package/router/dist/sandbox/script-sandbox.d.ts +0 -134
- package/router/dist/sandbox/script-sandbox.js +0 -337
- package/router/dist/setup/script-transform-adapters.d.ts +0 -32
- package/router/dist/setup/script-transform-adapters.js +0 -278
- package/router/dist/tools/batch.d.ts +0 -33
- package/router/dist/tools/batch.js +0 -586
- package/router/dist/tools/run.d.ts +0 -62
- package/router/dist/tools/run.js +0 -1304
- package/router/dist/tools/search.d.ts +0 -66
- package/router/dist/tools/search.js +0 -1364
- package/router/dist/transform/engine.d.ts +0 -168
- package/router/dist/transform/engine.js +0 -2072
- package/router/dist/vault/vault-index.d.ts +0 -125
- package/router/dist/vault/vault-index.js +0 -416
- package/router/dist/vault/vault.d.ts +0 -138
- package/router/dist/vault/vault.js +0 -630
- package/runtime/interaction-contract.md +0 -16
- package/skills/discuss/references/checkpoints.md +0 -66
- package/skills/execute-work/references/execution-loop.md +0 -77
- package/skills/output-router/SKILL.md +0 -206
- package/skills/output-router/references/safety-policy.md +0 -40
- package/skills/setup-freeflow/references/output-router-setup.md +0 -110
- package/skills/track-work/references/working-record-schema.md +0 -378
- package/skills/workflow/references/workflow-loop.md +0 -92
- /package/skills/handoff/references/{templates.md → handoff-templates.md} +0 -0
- /package/skills/review-artifact/references/{reviewer-prompt.md → independent-artifact-reviewer-contract.md} +0 -0
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import { readFile } from "node:fs/promises";
|
|
2
2
|
import { join } from "node:path";
|
|
3
3
|
import { fileURLToPath } from "node:url";
|
|
4
|
-
import {
|
|
4
|
+
import { resolveCognitiveRoutingState } from "../cognitive-routing/runtime.js";
|
|
5
|
+
import { isPiFlowHost } from "./runtime-identity.js";
|
|
5
6
|
export const VALID_MODES = new Set(["conversation", "workflow", "strict-workflow"]);
|
|
6
7
|
export const WORKFLOW_COMMANDS = [
|
|
7
8
|
{ command: "discuss", skill: "discuss" },
|
|
8
|
-
{ command: "
|
|
9
|
+
{ command: "action-selection", skill: "action-selection" },
|
|
9
10
|
{ command: "track-work", skill: "track-work" },
|
|
10
11
|
{ command: "write-spec", skill: "write-spec" },
|
|
11
12
|
{ command: "review-artifact", skill: "review-artifact" },
|
|
12
13
|
{ command: "write-plan", skill: "write-plan" },
|
|
13
14
|
{ command: "execute-work", skill: "execute-work" },
|
|
14
|
-
{ command: "execute-plan", skill: "execute-work" },
|
|
15
15
|
{ command: "simplify-code", skill: "simplify-code" },
|
|
16
16
|
{ command: "migration-work", skill: "migration-work" },
|
|
17
17
|
{ command: "diagnose-failure", skill: "diagnose-failure" },
|
|
@@ -26,6 +26,7 @@ export const WORKFLOW_COMMANDS = [
|
|
|
26
26
|
];
|
|
27
27
|
export const CONTRIBUTOR_COMMANDS = ["setup-freeflow", "write-skill", "evaluate-skill"];
|
|
28
28
|
export const FREEFLOW_MODEL_SKILL_NAMES = [
|
|
29
|
+
"action-selection",
|
|
29
30
|
"bypass",
|
|
30
31
|
"commit-work",
|
|
31
32
|
"decision-gate",
|
|
@@ -52,54 +53,107 @@ export const FREEFLOW_MODEL_SKILL_NAMES = [
|
|
|
52
53
|
"write-skill",
|
|
53
54
|
"write-spec",
|
|
54
55
|
];
|
|
56
|
+
export const FREEFLOW_CAPABILITY_SKILL_NAMES = ["cognitive-routing", "context-virtualization", "conversation-history"];
|
|
55
57
|
export function freeflowSkillPath(skillName) {
|
|
56
58
|
return fileURLToPath(new URL(`../../../skills/${skillName}/SKILL.md`, import.meta.url));
|
|
57
59
|
}
|
|
58
|
-
export function
|
|
59
|
-
return
|
|
60
|
+
export function freeflowCapabilitySkillPath(skillName) {
|
|
61
|
+
return fileURLToPath(new URL(`../../../capabilities/${skillName}/SKILL.md`, import.meta.url));
|
|
62
|
+
}
|
|
63
|
+
export function freeflowModelSkillPaths(capabilityState = undefined) {
|
|
64
|
+
const paths = FREEFLOW_MODEL_SKILL_NAMES.map((skillName) => freeflowSkillPath(skillName));
|
|
65
|
+
const capabilityStates = {
|
|
66
|
+
"cognitive-routing": capabilityState?.cognitiveRouting,
|
|
67
|
+
"context-virtualization": capabilityState?.contextVirtualization,
|
|
68
|
+
"conversation-history": capabilityState?.conversationHistory,
|
|
69
|
+
};
|
|
70
|
+
for (const skillName of FREEFLOW_CAPABILITY_SKILL_NAMES) {
|
|
71
|
+
if (capabilityStates[skillName]?.effective === true) {
|
|
72
|
+
paths.push(freeflowCapabilitySkillPath(skillName));
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return paths;
|
|
60
76
|
}
|
|
61
77
|
const MODE_STATE_ENTRY = "freeflow-mode";
|
|
62
78
|
const SESSION_OVERRIDES_ENTRY = "freeflow-session-overrides";
|
|
63
|
-
const SESSION_CORE_KEYS = new Set([
|
|
79
|
+
const SESSION_CORE_KEYS = new Set([
|
|
80
|
+
"enabled",
|
|
81
|
+
"interactionContract",
|
|
82
|
+
"skillsEnabled",
|
|
83
|
+
"contextVirtualization",
|
|
84
|
+
"conversationHistory",
|
|
85
|
+
]);
|
|
64
86
|
const RESET_MODE_ARGS = new Set(["reset"]);
|
|
65
|
-
export const
|
|
66
|
-
export const
|
|
87
|
+
export const COGNITIVE_ROUTING_SWITCH_TOOL_NAME = "freeflow_switch_profile";
|
|
88
|
+
export const FREEFLOW_RUNTIME_STATE_MESSAGE_TYPE = "freeflow-runtime-state";
|
|
89
|
+
export const COGNITIVE_ROUTING_RUNTIME_STATE_MESSAGE_TYPE = "freeflow-cognitive-routing-runtime-state";
|
|
67
90
|
export const WORKFLOW_BOOTSTRAP_MESSAGE_TYPE = "freeflow-workflow-bootstrap";
|
|
91
|
+
export const COGNITIVE_ROUTING_BOOTSTRAP_MESSAGE_TYPE = "freeflow-cognitive-routing-bootstrap";
|
|
92
|
+
export const FREEFLOW_BOOTSTRAP_MESSAGE_TYPE = "freeflow-bootstrap";
|
|
68
93
|
let runtimeContextCache = null;
|
|
69
94
|
let currentModeOverride = null;
|
|
70
95
|
let currentSessionOverrides = {};
|
|
71
|
-
|
|
96
|
+
async function readPromptFile(url) {
|
|
97
|
+
try {
|
|
98
|
+
return await readFile(url, "utf8");
|
|
99
|
+
} catch {
|
|
100
|
+
return null;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
72
103
|
async function loadRuntimeContext(capabilityState = undefined) {
|
|
104
|
+
const freeflowEnabled = capabilityState?.enabled === true;
|
|
73
105
|
const interactionContractEnabled = capabilityState?.interactionContract?.effective === true;
|
|
74
106
|
const skillsEnabled = capabilityState?.skills?.effective === true;
|
|
75
|
-
const
|
|
76
|
-
const
|
|
107
|
+
const contextVirtualizationEnabled = capabilityState?.contextVirtualization?.effective === true;
|
|
108
|
+
const conversationHistoryEnabled = capabilityState?.conversationHistory?.effective === true;
|
|
109
|
+
const cognitiveRoutingEnabled = capabilityState?.cognitiveRouting?.effective === true;
|
|
110
|
+
const [
|
|
111
|
+
corePrompt,
|
|
112
|
+
interactionContractPrompt,
|
|
113
|
+
skillsPrompt,
|
|
114
|
+
cognitiveRoutingPrompt,
|
|
115
|
+
contextVirtualizationPrompt,
|
|
116
|
+
conversationHistoryPrompt,
|
|
117
|
+
] = await Promise.all([
|
|
118
|
+
freeflowEnabled
|
|
119
|
+
? readPromptFile(new URL("../../../runtime/prompts/core.md", import.meta.url))
|
|
120
|
+
: Promise.resolve(null),
|
|
77
121
|
interactionContractEnabled
|
|
78
|
-
?
|
|
122
|
+
? readPromptFile(new URL("../../../runtime/prompts/interaction-contract.md", import.meta.url))
|
|
79
123
|
: Promise.resolve(null),
|
|
80
124
|
skillsEnabled
|
|
81
|
-
?
|
|
125
|
+
? readPromptFile(new URL("../../../runtime/prompts/skills.md", import.meta.url))
|
|
126
|
+
: Promise.resolve(null),
|
|
127
|
+
cognitiveRoutingEnabled
|
|
128
|
+
? readPromptFile(new URL("../../../runtime/prompts/cognitive-routing.md", import.meta.url))
|
|
82
129
|
: Promise.resolve(null),
|
|
83
|
-
|
|
84
|
-
?
|
|
130
|
+
contextVirtualizationEnabled
|
|
131
|
+
? readPromptFile(new URL("../../../runtime/prompts/context-virtualization.md", import.meta.url))
|
|
132
|
+
: Promise.resolve(null),
|
|
133
|
+
conversationHistoryEnabled
|
|
134
|
+
? readPromptFile(new URL("../../../runtime/prompts/conversation-history.md", import.meta.url))
|
|
85
135
|
: Promise.resolve(null),
|
|
86
136
|
]);
|
|
87
|
-
return {
|
|
137
|
+
return {
|
|
138
|
+
corePrompt,
|
|
139
|
+
interactionContractPrompt,
|
|
140
|
+
skillsPrompt,
|
|
141
|
+
cognitiveRoutingPrompt,
|
|
142
|
+
contextVirtualizationPrompt,
|
|
143
|
+
conversationHistoryPrompt,
|
|
144
|
+
};
|
|
88
145
|
}
|
|
89
146
|
function runtimeContextCacheSatisfies(capabilityState) {
|
|
90
|
-
if (!runtimeContextCache)
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
return false;
|
|
101
|
-
}
|
|
102
|
-
return true;
|
|
147
|
+
if (!runtimeContextCache) return false;
|
|
148
|
+
const expected = {
|
|
149
|
+
corePrompt: capabilityState?.enabled === true,
|
|
150
|
+
interactionContractPrompt: capabilityState?.interactionContract?.effective === true,
|
|
151
|
+
skillsPrompt: capabilityState?.skills?.effective === true,
|
|
152
|
+
cognitiveRoutingPrompt: capabilityState?.cognitiveRouting?.effective === true,
|
|
153
|
+
contextVirtualizationPrompt: capabilityState?.contextVirtualization?.effective === true,
|
|
154
|
+
conversationHistoryPrompt: capabilityState?.conversationHistory?.effective === true,
|
|
155
|
+
};
|
|
156
|
+
return Object.entries(expected).every(([key, required]) => !required || Boolean(runtimeContextCache[key]));
|
|
103
157
|
}
|
|
104
158
|
export async function refreshRuntimeContext(capabilityState = undefined) {
|
|
105
159
|
runtimeContextCache = await loadRuntimeContext(capabilityState);
|
|
@@ -111,41 +165,32 @@ export async function getRuntimeContext(capabilityState = undefined) {
|
|
|
111
165
|
}
|
|
112
166
|
return refreshRuntimeContext(capabilityState);
|
|
113
167
|
}
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
if (
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
168
|
+
const BOOTSTRAP_COMPONENTS = Object.freeze({
|
|
169
|
+
workflow: "workflow",
|
|
170
|
+
cognitiveRouting: "cognitive-routing",
|
|
171
|
+
});
|
|
172
|
+
function bootstrapEntryComponents(entry) {
|
|
173
|
+
const isCustomMessage = entry?.role === "custom" || entry?.type === "custom_message" || entry?.type === "custom";
|
|
174
|
+
if (!isCustomMessage) return [];
|
|
175
|
+
if (entry.customType === FREEFLOW_BOOTSTRAP_MESSAGE_TYPE) {
|
|
176
|
+
if (Array.isArray(entry.details?.components)) return entry.details.components;
|
|
177
|
+
return [
|
|
178
|
+
...(entry.content?.includes("<!-- freeflow-bootstrap:workflow -->") ? [BOOTSTRAP_COMPONENTS.workflow] : []),
|
|
179
|
+
...(entry.content?.includes("<!-- freeflow-bootstrap:cognitive-routing -->")
|
|
180
|
+
? [BOOTSTRAP_COMPONENTS.cognitiveRouting]
|
|
181
|
+
: []),
|
|
182
|
+
];
|
|
183
|
+
}
|
|
184
|
+
if (entry.customType === WORKFLOW_BOOTSTRAP_MESSAGE_TYPE) {
|
|
185
|
+
return [BOOTSTRAP_COMPONENTS.workflow];
|
|
186
|
+
}
|
|
187
|
+
if (entry.customType === COGNITIVE_ROUTING_BOOTSTRAP_MESSAGE_TYPE) {
|
|
188
|
+
return [BOOTSTRAP_COMPONENTS.cognitiveRouting];
|
|
130
189
|
}
|
|
131
190
|
return [];
|
|
132
191
|
}
|
|
133
|
-
export function
|
|
134
|
-
|
|
135
|
-
return undefined;
|
|
136
|
-
}
|
|
137
|
-
const alreadyLoaded = activeSessionEntries(sessionManager).some(
|
|
138
|
-
(entry) => entry?.type === "custom_message" && entry?.customType === WORKFLOW_BOOTSTRAP_MESSAGE_TYPE,
|
|
139
|
-
);
|
|
140
|
-
if (alreadyLoaded) {
|
|
141
|
-
return undefined;
|
|
142
|
-
}
|
|
143
|
-
return {
|
|
144
|
-
customType: WORKFLOW_BOOTSTRAP_MESSAGE_TYPE,
|
|
145
|
-
content: `# Freeflow Workflow Bootstrap\n\n${freeflowContext.workflowSkill.trim()}`,
|
|
146
|
-
display: false,
|
|
147
|
-
details: { skill: "workflow", source: "first-turn-bootstrap" },
|
|
148
|
-
};
|
|
192
|
+
export function filterBootstrapMessage(message) {
|
|
193
|
+
return bootstrapEntryComponents(message).length === 0 ? message : undefined;
|
|
149
194
|
}
|
|
150
195
|
function isRecord(value) {
|
|
151
196
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
@@ -157,6 +202,12 @@ function validateCoreConfigFields(value) {
|
|
|
157
202
|
if (value.enabled !== undefined && typeof value.enabled !== "boolean") {
|
|
158
203
|
return "enabled must be a boolean";
|
|
159
204
|
}
|
|
205
|
+
if (value.contextVirtualization !== undefined && typeof value.contextVirtualization !== "boolean") {
|
|
206
|
+
return "contextVirtualization must be a boolean";
|
|
207
|
+
}
|
|
208
|
+
if (value.conversationHistory !== undefined && typeof value.conversationHistory !== "boolean") {
|
|
209
|
+
return "conversationHistory must be a boolean";
|
|
210
|
+
}
|
|
160
211
|
if (value.interactionContract !== undefined && typeof value.interactionContract !== "boolean") {
|
|
161
212
|
return "interactionContract must be a boolean";
|
|
162
213
|
}
|
|
@@ -179,6 +230,7 @@ function validateFreeflowConfigShape(value) {
|
|
|
179
230
|
if (!isRecord(value)) {
|
|
180
231
|
return "config must be a JSON object";
|
|
181
232
|
}
|
|
233
|
+
// Keep retired capability keys shape-tolerated so existing repositories remain activated; runtime behavior ignores them.
|
|
182
234
|
const allowedKeys = new Set([
|
|
183
235
|
"enabled",
|
|
184
236
|
"defaultMode",
|
|
@@ -187,6 +239,9 @@ function validateFreeflowConfigShape(value) {
|
|
|
187
239
|
"outputRouter",
|
|
188
240
|
"observedRouting",
|
|
189
241
|
"scriptTransform",
|
|
242
|
+
"cognitiveRouting",
|
|
243
|
+
"contextVirtualization",
|
|
244
|
+
"conversationHistory",
|
|
190
245
|
]);
|
|
191
246
|
for (const key of Object.keys(value)) {
|
|
192
247
|
if (!allowedKeys.has(key)) {
|
|
@@ -206,7 +261,16 @@ function validateFreeflowLocalConfigShape(value) {
|
|
|
206
261
|
if (!isRecord(value)) {
|
|
207
262
|
return "local config must be a JSON object";
|
|
208
263
|
}
|
|
209
|
-
const allowedKeys = new Set([
|
|
264
|
+
const allowedKeys = new Set([
|
|
265
|
+
"enabled",
|
|
266
|
+
"defaultMode",
|
|
267
|
+
"interactionContract",
|
|
268
|
+
"skills",
|
|
269
|
+
"processing",
|
|
270
|
+
"cognitiveRouting",
|
|
271
|
+
"contextVirtualization",
|
|
272
|
+
"conversationHistory",
|
|
273
|
+
]);
|
|
210
274
|
for (const key of Object.keys(value)) {
|
|
211
275
|
if (!allowedKeys.has(key)) {
|
|
212
276
|
return `unsupported top-level local config key: ${key}`;
|
|
@@ -276,6 +340,8 @@ function resolveLayeredValue(repository, local, key, fallback) {
|
|
|
276
340
|
function resolveCoreConfig(repository, local) {
|
|
277
341
|
const enabled = resolveLayeredValue(repository, local, "enabled", true);
|
|
278
342
|
const interactionContract = resolveLayeredValue(repository, local, "interactionContract", true);
|
|
343
|
+
const contextVirtualization = resolveLayeredValue(repository, local, "contextVirtualization", false);
|
|
344
|
+
const conversationHistory = resolveLayeredValue(repository, local, "conversationHistory", false);
|
|
279
345
|
const defaultMode = resolveLayeredValue(repository, local, "defaultMode", "workflow");
|
|
280
346
|
const repositorySkills = isRecord(repository.skills) ? repository.skills : {};
|
|
281
347
|
const localSkills = isRecord(local.skills) ? local.skills : {};
|
|
@@ -284,12 +350,16 @@ function resolveCoreConfig(repository, local) {
|
|
|
284
350
|
config: {
|
|
285
351
|
enabled: enabled.value,
|
|
286
352
|
interactionContract: interactionContract.value,
|
|
353
|
+
contextVirtualization: contextVirtualization.value,
|
|
354
|
+
conversationHistory: conversationHistory.value,
|
|
287
355
|
skills: { enabled: skillsEnabled.value },
|
|
288
356
|
defaultMode: defaultMode.value,
|
|
289
357
|
},
|
|
290
358
|
sources: {
|
|
291
359
|
enabled: enabled.source,
|
|
292
360
|
interactionContract: interactionContract.source,
|
|
361
|
+
contextVirtualization: contextVirtualization.source,
|
|
362
|
+
conversationHistory: conversationHistory.source,
|
|
293
363
|
skillsEnabled: skillsEnabled.source,
|
|
294
364
|
defaultMode: defaultMode.source,
|
|
295
365
|
},
|
|
@@ -310,18 +380,26 @@ function resolveSessionCoreConfig(layers) {
|
|
|
310
380
|
const sources = layers.sources;
|
|
311
381
|
const enabled = currentSessionOverrides.enabled;
|
|
312
382
|
const interactionContract = currentSessionOverrides.interactionContract;
|
|
383
|
+
const contextVirtualization = currentSessionOverrides.contextVirtualization;
|
|
384
|
+
const conversationHistory = currentSessionOverrides.conversationHistory;
|
|
313
385
|
const skillsEnabled = currentSessionOverrides.skillsEnabled;
|
|
314
386
|
return {
|
|
315
387
|
config: {
|
|
316
388
|
enabled: typeof enabled === "boolean" ? enabled : configured.enabled,
|
|
317
389
|
interactionContract:
|
|
318
390
|
typeof interactionContract === "boolean" ? interactionContract : configured.interactionContract,
|
|
391
|
+
contextVirtualization:
|
|
392
|
+
typeof contextVirtualization === "boolean" ? contextVirtualization : configured.contextVirtualization,
|
|
393
|
+
conversationHistory:
|
|
394
|
+
typeof conversationHistory === "boolean" ? conversationHistory : configured.conversationHistory,
|
|
319
395
|
skills: { enabled: typeof skillsEnabled === "boolean" ? skillsEnabled : configured.skills.enabled },
|
|
320
396
|
defaultMode: configured.defaultMode,
|
|
321
397
|
},
|
|
322
398
|
sources: {
|
|
323
399
|
enabled: typeof enabled === "boolean" ? "session" : sources.enabled,
|
|
324
400
|
interactionContract: typeof interactionContract === "boolean" ? "session" : sources.interactionContract,
|
|
401
|
+
contextVirtualization: typeof contextVirtualization === "boolean" ? "session" : sources.contextVirtualization,
|
|
402
|
+
conversationHistory: typeof conversationHistory === "boolean" ? "session" : sources.conversationHistory,
|
|
325
403
|
skillsEnabled: typeof skillsEnabled === "boolean" ? "session" : sources.skillsEnabled,
|
|
326
404
|
defaultMode: sources.defaultMode,
|
|
327
405
|
},
|
|
@@ -351,15 +429,60 @@ export async function readFreeflowConfigLayers(cwd) {
|
|
|
351
429
|
parseError: blockingState?.parseError ?? null,
|
|
352
430
|
};
|
|
353
431
|
}
|
|
354
|
-
export async function readCapabilityState(cwd) {
|
|
432
|
+
export async function readCapabilityState(cwd, host = undefined, extensionHost = undefined) {
|
|
355
433
|
const layers = await readFreeflowConfigLayers(cwd);
|
|
356
|
-
const parsed = layers.repository.valid ? layers.repository.parsed : {};
|
|
357
|
-
const normalized = normalizeFreeflowConfig(parsed);
|
|
358
434
|
const effectiveCore = resolveSessionCoreConfig(layers);
|
|
359
435
|
const enabled = layers.configured && effectiveCore.config.enabled;
|
|
360
436
|
const interactionContractConfigEnabled = effectiveCore.config.interactionContract;
|
|
361
437
|
const skillsConfigEnabled = effectiveCore.config.skills.enabled;
|
|
362
|
-
const
|
|
438
|
+
const contextVirtualizationConfigEnabled = effectiveCore.config.contextVirtualization;
|
|
439
|
+
const conversationHistoryConfigEnabled = effectiveCore.config.conversationHistory;
|
|
440
|
+
const skillsEffective = enabled && skillsConfigEnabled;
|
|
441
|
+
const hostSupportsCognitiveRouting = isPiFlowHost(extensionHost);
|
|
442
|
+
const configuredCognitiveRouting = await resolveCognitiveRoutingState(
|
|
443
|
+
layers.repository.parsed,
|
|
444
|
+
layers.local.parsed,
|
|
445
|
+
hostSupportsCognitiveRouting ? host : undefined,
|
|
446
|
+
);
|
|
447
|
+
const disabledReason = enabled
|
|
448
|
+
? skillsEffective
|
|
449
|
+
? undefined
|
|
450
|
+
: { code: "disabled", message: "Skills are disabled" }
|
|
451
|
+
: { code: "disabled", message: "Freeflow is disabled" };
|
|
452
|
+
const childCapability = (configuredEnabled) => ({
|
|
453
|
+
enabled: configuredEnabled,
|
|
454
|
+
effective: skillsEffective && configuredEnabled,
|
|
455
|
+
...(disabledReason ? { blockingReason: disabledReason } : {}),
|
|
456
|
+
});
|
|
457
|
+
const cognitiveRouting = enabled
|
|
458
|
+
? skillsEffective
|
|
459
|
+
? !hostSupportsCognitiveRouting && configuredCognitiveRouting.configValid
|
|
460
|
+
? {
|
|
461
|
+
...configuredCognitiveRouting,
|
|
462
|
+
effective: false,
|
|
463
|
+
blockingReason: {
|
|
464
|
+
code: "runtime_disabled",
|
|
465
|
+
message: "Cognitive Routing is disabled outside the PiFlow runtime",
|
|
466
|
+
},
|
|
467
|
+
}
|
|
468
|
+
: configuredCognitiveRouting
|
|
469
|
+
: {
|
|
470
|
+
...configuredCognitiveRouting,
|
|
471
|
+
effective: false,
|
|
472
|
+
blockingReason: {
|
|
473
|
+
code: "disabled",
|
|
474
|
+
message: "Skills are disabled",
|
|
475
|
+
},
|
|
476
|
+
}
|
|
477
|
+
: {
|
|
478
|
+
...configuredCognitiveRouting,
|
|
479
|
+
enabled: false,
|
|
480
|
+
effective: false,
|
|
481
|
+
blockingReason: {
|
|
482
|
+
code: "disabled",
|
|
483
|
+
message: "Freeflow is disabled",
|
|
484
|
+
},
|
|
485
|
+
};
|
|
363
486
|
return {
|
|
364
487
|
configured: layers.configured,
|
|
365
488
|
repositoryConfigured: layers.repositoryConfigured,
|
|
@@ -385,63 +508,13 @@ export async function readCapabilityState(cwd) {
|
|
|
385
508
|
enabled: skillsConfigEnabled,
|
|
386
509
|
effective: enabled && skillsConfigEnabled,
|
|
387
510
|
},
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
511
|
+
contextVirtualization: childCapability(contextVirtualizationConfigEnabled),
|
|
512
|
+
conversationHistory: childCapability(conversationHistoryConfigEnabled),
|
|
513
|
+
hostSupportsCognitiveRouting,
|
|
514
|
+
cognitiveRouting,
|
|
392
515
|
};
|
|
393
516
|
}
|
|
394
517
|
export const readRuntimeState = readCapabilityState;
|
|
395
|
-
export async function readOutputRouterConfig(cwd) {
|
|
396
|
-
const layers = await readFreeflowConfigLayers(cwd);
|
|
397
|
-
const parsed = layers.repository.valid ? layers.repository.parsed : {};
|
|
398
|
-
const localParsed = layers.local.valid ? layers.local.parsed : {};
|
|
399
|
-
const normalized = normalizeFreeflowConfig(parsed);
|
|
400
|
-
const local = normalizeLocalFreeflowConfig(localParsed);
|
|
401
|
-
const freeflowEnabled = layers.configured && layers.coreConfig.enabled;
|
|
402
|
-
const effectiveConfig = freeflowEnabled
|
|
403
|
-
? normalized.config
|
|
404
|
-
: {
|
|
405
|
-
...normalized.config,
|
|
406
|
-
outputRouter: { ...normalized.config.outputRouter, enabled: false },
|
|
407
|
-
observedRouting: {
|
|
408
|
-
...normalized.config.observedRouting,
|
|
409
|
-
enabled: false,
|
|
410
|
-
},
|
|
411
|
-
scriptTransform: {
|
|
412
|
-
...normalized.config.scriptTransform,
|
|
413
|
-
enabled: false,
|
|
414
|
-
},
|
|
415
|
-
};
|
|
416
|
-
const configWarnings = [...normalized.warnings];
|
|
417
|
-
if (layers.repository.exists && !layers.repository.valid) {
|
|
418
|
-
configWarnings.unshift(
|
|
419
|
-
`.freeflow/config.json could not be parsed; Freeflow runtime is inactive. ${layers.repository.parseError ?? ""}`.trim(),
|
|
420
|
-
);
|
|
421
|
-
}
|
|
422
|
-
if (layers.local.exists && !layers.local.valid) {
|
|
423
|
-
configWarnings.unshift(
|
|
424
|
-
`.freeflow/local.json could not be parsed; Freeflow runtime is inactive. ${layers.local.parseError ?? ""}`.trim(),
|
|
425
|
-
);
|
|
426
|
-
}
|
|
427
|
-
return {
|
|
428
|
-
config: effectiveConfig.outputRouter,
|
|
429
|
-
freeflowConfig: effectiveConfig,
|
|
430
|
-
localConfig: local.config,
|
|
431
|
-
warnings: [...configWarnings, ...local.warnings],
|
|
432
|
-
};
|
|
433
|
-
}
|
|
434
|
-
export function notifyRouterConfigWarnings(ctx, routerConfigResult) {
|
|
435
|
-
if (!routerConfigResult.warnings.length) {
|
|
436
|
-
return;
|
|
437
|
-
}
|
|
438
|
-
const key = routerConfigResult.warnings.join("\n");
|
|
439
|
-
if (key === lastRouterConfigWarningKey) {
|
|
440
|
-
return;
|
|
441
|
-
}
|
|
442
|
-
lastRouterConfigWarningKey = key;
|
|
443
|
-
ctx.ui.notify(`Freeflow config warning: ${routerConfigResult.warnings.join(" ")}`, "warning");
|
|
444
|
-
}
|
|
445
518
|
export function restoreModeOverride(ctx) {
|
|
446
519
|
currentModeOverride = null;
|
|
447
520
|
currentSessionOverrides = {};
|
|
@@ -479,7 +552,13 @@ export async function readModeState(cwd) {
|
|
|
479
552
|
effectiveMode: active ? resolvedMode : null,
|
|
480
553
|
};
|
|
481
554
|
}
|
|
482
|
-
export function setModeStatus(
|
|
555
|
+
export function setModeStatus(
|
|
556
|
+
ctx,
|
|
557
|
+
modeState,
|
|
558
|
+
capabilityState = undefined,
|
|
559
|
+
cognitiveRoutingRuntime = undefined,
|
|
560
|
+
options = {},
|
|
561
|
+
) {
|
|
483
562
|
if (capabilityState && !capabilityState.configured) {
|
|
484
563
|
ctx.ui.setStatus("freeflow", capabilityState.configExists ? "freeflow: config error" : "freeflow: setup needed");
|
|
485
564
|
return;
|
|
@@ -500,8 +579,39 @@ export function setModeStatus(ctx, modeState, capabilityState = undefined) {
|
|
|
500
579
|
} else if (capabilityState?.configSources?.skillsEnabled === "session") {
|
|
501
580
|
active.push("skills off (session)");
|
|
502
581
|
}
|
|
503
|
-
|
|
504
|
-
|
|
582
|
+
const cognitiveRouting = capabilityState?.cognitiveRouting;
|
|
583
|
+
const cognitiveRoutingActive = cognitiveRouting?.effective === true && cognitiveRoutingRuntime?.effective === true;
|
|
584
|
+
const startupSelectionSuppressesCognitiveRouting =
|
|
585
|
+
ctx?.modelStateProvenance?.explicitModel === true || ctx?.modelStateProvenance?.explicitThinking === true;
|
|
586
|
+
if (cognitiveRoutingActive) {
|
|
587
|
+
const profile = cognitiveRoutingRuntime.activeProfile;
|
|
588
|
+
const control =
|
|
589
|
+
cognitiveRoutingRuntime.controlMode === "manual-standard" ||
|
|
590
|
+
cognitiveRoutingRuntime.controlMode === "manual-reasoning"
|
|
591
|
+
? "manual hold"
|
|
592
|
+
: "automatic";
|
|
593
|
+
active.push(`${profile} · ${control}`);
|
|
594
|
+
} else if (cognitiveRouting?.enabled === true) {
|
|
595
|
+
if (cognitiveRouting.blockingReason?.code === "runtime_disabled") {
|
|
596
|
+
active.push("cognitive disabled · PiFlow only");
|
|
597
|
+
} else if (
|
|
598
|
+
cognitiveRouting.effective === true &&
|
|
599
|
+
cognitiveRoutingRuntime === undefined &&
|
|
600
|
+
options.cognitiveRoutingStartupPending === true &&
|
|
601
|
+
!startupSelectionSuppressesCognitiveRouting
|
|
602
|
+
) {
|
|
603
|
+
const startupProfile = cognitiveRouting.sessionStart?.profile ?? "standard";
|
|
604
|
+
active.push(`${startupProfile} · pending`);
|
|
605
|
+
} else {
|
|
606
|
+
const reason =
|
|
607
|
+
cognitiveRouting?.effective === true
|
|
608
|
+
? (cognitiveRoutingRuntime?.blockingReason?.code ?? "runtime_inactive")
|
|
609
|
+
: (cognitiveRouting.blockingReason?.code ?? "unavailable");
|
|
610
|
+
active.push(`cognitive blocked · ${reason}`);
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
if (capabilityState?.contextVirtualization?.effective || capabilityState?.conversationHistory?.effective) {
|
|
614
|
+
active.push("context");
|
|
505
615
|
}
|
|
506
616
|
ctx.ui.setStatus("freeflow", `freeflow: ${active.length > 0 ? active.join(" · ") : "idle"}`);
|
|
507
617
|
}
|
|
@@ -521,156 +631,93 @@ export function skillPrompt(skill, args) {
|
|
|
521
631
|
const trimmed = args?.trim();
|
|
522
632
|
return trimmed ? `/skill:${skill}\n\n${trimmed}` : `/skill:${skill}`;
|
|
523
633
|
}
|
|
524
|
-
function
|
|
525
|
-
if (
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
\`\`\`md
|
|
546
|
-
${freeflowContext.outputRouterSkill.trim()}
|
|
547
|
-
\`\`\``;
|
|
548
|
-
}
|
|
549
|
-
function capabilityContext(capabilityState) {
|
|
550
|
-
const sessionSuffix = (source) => (source === "session" ? " (session override)" : "");
|
|
551
|
-
const interactionContract = `${capabilityState.interactionContract.effective ? "enabled" : "disabled"}${sessionSuffix(capabilityState.configSources.interactionContract)}`;
|
|
552
|
-
const skills = `${capabilityState.skills.effective ? "enabled" : "disabled"}${sessionSuffix(capabilityState.configSources.skillsEnabled)}`;
|
|
553
|
-
const outputRouter = capabilityState.outputRouter.enabled ? "enabled" : "disabled";
|
|
554
|
-
return `## Freeflow Capabilities
|
|
555
|
-
|
|
556
|
-
- Interaction contract: ${interactionContract}. Configure with \`/freeflow settings\` or temporarily with \`/freeflow settings session\`; inspect with \`/freeflow status\`.
|
|
557
|
-
- Skills: ${skills}. Configure with \`/freeflow settings\` or temporarily with \`/freeflow settings session\`; inspect with \`/freeflow status\`.
|
|
558
|
-
- Output router: ${outputRouter}. Configure with \`/freeflow settings\` or \`/output-router\`; inspect with \`/output-router status\`.
|
|
559
|
-
|
|
560
|
-
Disabled capabilities are named only for status/config awareness. Capability-specific instructions and tools are active only while that capability is enabled.`;
|
|
561
|
-
}
|
|
562
|
-
function hasModelFacingCapability(capabilityState) {
|
|
563
|
-
return (
|
|
564
|
-
capabilityState.interactionContract.effective ||
|
|
565
|
-
capabilityState.skills.effective ||
|
|
566
|
-
capabilityState.outputRouter.enabled
|
|
634
|
+
function publicCognitiveRoutingControl(controlMode) {
|
|
635
|
+
if (controlMode === "automatic") return "automatic";
|
|
636
|
+
if (controlMode === "manual-standard" || controlMode === "manual-reasoning") return "manual";
|
|
637
|
+
return "unavailable";
|
|
638
|
+
}
|
|
639
|
+
function publicCognitiveRoutingProfile(activeProfile, effective) {
|
|
640
|
+
if (effective !== true) return "unavailable";
|
|
641
|
+
return activeProfile === "standard" || activeProfile === "reasoning" ? activeProfile : "unavailable";
|
|
642
|
+
}
|
|
643
|
+
function publicCapabilityStatus(capability) {
|
|
644
|
+
if (capability?.effective === true) return "active";
|
|
645
|
+
if (!capability) return "unavailable";
|
|
646
|
+
const blockingCode = capability.blockingReason?.code;
|
|
647
|
+
if (blockingCode && blockingCode !== "disabled") return "unavailable";
|
|
648
|
+
return "inactive";
|
|
649
|
+
}
|
|
650
|
+
export function freeflowRuntimeStateMessage(modeState, capabilityState, cognitiveRoutingRuntime = undefined) {
|
|
651
|
+
const cognitiveRoutingEffective = capabilityState?.cognitiveRouting?.effective === true;
|
|
652
|
+
const profile = publicCognitiveRoutingProfile(
|
|
653
|
+
cognitiveRoutingRuntime?.activeProfile,
|
|
654
|
+
cognitiveRoutingEffective && cognitiveRoutingRuntime?.effective === true,
|
|
567
655
|
);
|
|
656
|
+
const control =
|
|
657
|
+
profile === "unavailable" ? "unavailable" : publicCognitiveRoutingControl(cognitiveRoutingRuntime?.controlMode);
|
|
658
|
+
const defaultMode = modeState?.defaultMode ?? "workflow";
|
|
659
|
+
const activeMode = modeState?.effectiveMode ?? "inactive";
|
|
660
|
+
return {
|
|
661
|
+
role: "custom",
|
|
662
|
+
customType: FREEFLOW_RUNTIME_STATE_MESSAGE_TYPE,
|
|
663
|
+
content: [
|
|
664
|
+
"# Freeflow Runtime State",
|
|
665
|
+
"",
|
|
666
|
+
"This is extension-generated runtime state. Use it to interpret the stable Freeflow guidance.",
|
|
667
|
+
"",
|
|
668
|
+
`Default mode: \`${defaultMode}\``,
|
|
669
|
+
`Active mode: \`${activeMode}\``,
|
|
670
|
+
"",
|
|
671
|
+
"Capabilities:",
|
|
672
|
+
`- Interaction Contract: ${publicCapabilityStatus(capabilityState?.interactionContract)}`,
|
|
673
|
+
`- Skills: ${publicCapabilityStatus(capabilityState?.skills)}`,
|
|
674
|
+
`- Context Virtualization: ${publicCapabilityStatus(capabilityState?.contextVirtualization)}`,
|
|
675
|
+
`- Conversation History: ${publicCapabilityStatus(capabilityState?.conversationHistory)}`,
|
|
676
|
+
`- Cognitive Routing: ${publicCapabilityStatus(capabilityState?.cognitiveRouting)}`,
|
|
677
|
+
"",
|
|
678
|
+
"Cognitive Routing:",
|
|
679
|
+
`- Control: \`${control}\``,
|
|
680
|
+
`- Profile: \`${profile}\``,
|
|
681
|
+
].join("\n"),
|
|
682
|
+
display: false,
|
|
683
|
+
details: { source: "provider-request-runtime-state" },
|
|
684
|
+
};
|
|
568
685
|
}
|
|
569
|
-
function
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
## Strict Workflow Overlay
|
|
585
|
-
|
|
586
|
-
Strict Workflow is active. Use the adaptive Workflow, but increase decision, evidence, verification, and checkpoint pressure at high-risk or hard-to-reverse boundaries.
|
|
587
|
-
|
|
588
|
-
For work affecting security, privacy, billing, data loss, migrations, public interfaces, compatibility, deployment, or architecture:
|
|
589
|
-
|
|
590
|
-
- stop for any user-owned choice or source conflict;
|
|
591
|
-
- inspect the relevant risk surface before crossing the boundary;
|
|
592
|
-
- select only artifacts, checkpoints, and independent review that materially reduce risk;
|
|
593
|
-
- verify at the affected boundary before claiming success.
|
|
594
|
-
|
|
595
|
-
Do not manufacture ceremony for low-risk, reversible work. Strict Workflow does not authorize mutation, bypass safety, or make every implementation detail a user decision.`;
|
|
596
|
-
}
|
|
597
|
-
return "";
|
|
598
|
-
}
|
|
599
|
-
function activeModeContext(modeState) {
|
|
600
|
-
return `## Freeflow Mode State
|
|
601
|
-
|
|
602
|
-
Repository default mode: \`${modeState.repositoryDefaultMode}\` (${modeState.repositoryDefaultModeSource}).
|
|
603
|
-
Personal default override: \`${modeState.personalDefaultMode ?? "none"}\`.
|
|
604
|
-
Configured default mode: \`${modeState.defaultMode}\` (${modeSourceLabel(modeState.defaultModeSource)}).
|
|
605
|
-
Session mode override: \`${modeState.sessionMode ?? "none"}\`.
|
|
606
|
-
Resolved mode: \`${modeState.resolvedMode}\`.
|
|
607
|
-
Effective Freeflow mode: \`${modeState.effectiveMode}\`.
|
|
608
|
-
|
|
609
|
-
Mode behavior:
|
|
610
|
-
- \`conversation\`: answer, discuss, critique, and inspect read-only; require a mode change before mutating state.
|
|
611
|
-
- \`workflow\`: use the adaptive workflow for consequential or mutating work.
|
|
612
|
-
- \`strict-workflow\`: use the same workflow with stronger decision, evidence, and checkpoint pressure at high-risk or hard-to-reverse boundaries.
|
|
613
|
-
|
|
614
|
-
Task type, risk classification, and direct skill calls do not change mode. Recommend another mode when useful; the user decides.
|
|
615
|
-
Do not announce mode on every reply. Mention it when the user asks, configuration is discussed, or it changes the next action.${modeOverlayContext(modeState.effectiveMode)}`;
|
|
616
|
-
}
|
|
617
|
-
function inactiveModeContext(modeState) {
|
|
618
|
-
return `## Freeflow Mode State
|
|
619
|
-
|
|
620
|
-
Repository default mode: \`${modeState.repositoryDefaultMode}\` (${modeState.repositoryDefaultModeSource}).
|
|
621
|
-
Personal default override: \`${modeState.personalDefaultMode ?? "none"}\`.
|
|
622
|
-
Configured default mode: \`${modeState.defaultMode}\` (${modeSourceLabel(modeState.defaultModeSource)}).
|
|
623
|
-
Session mode override: \`${modeState.sessionMode ?? "none"}\`.
|
|
624
|
-
Resolved mode: \`${modeState.resolvedMode}\` (inactive because Skills are disabled).
|
|
625
|
-
Effective Freeflow mode: \`none\`.
|
|
626
|
-
|
|
627
|
-
Freeflow workflow modes are dormant until Skills are enabled with \`/freeflow settings\`.`;
|
|
628
|
-
}
|
|
629
|
-
function controlPlaneContext(modeState, capabilityState) {
|
|
630
|
-
return `# Freeflow Control Plane
|
|
631
|
-
|
|
632
|
-
Freeflow is enabled for this repo, but no model-facing capabilities are enabled.
|
|
633
|
-
These lines are status/config awareness only; do not apply Freeflow workflow or output-router behavior.
|
|
634
|
-
|
|
635
|
-
${inactiveModeContext(modeState)}
|
|
636
|
-
|
|
637
|
-
${capabilityContext(capabilityState)}
|
|
638
|
-
|
|
639
|
-
Use \`/freeflow settings\` to enable the Interaction Contract, Skills, or Output Router. The read-only \`freeflow_status\` diagnostic may be available so the model can answer setup/status questions.`;
|
|
640
|
-
}
|
|
641
|
-
export function runtimeContext(modeState, freeflowContext, routerConfigResult, capabilityState) {
|
|
642
|
-
if (!capabilityState.configured) {
|
|
686
|
+
export function withoutFreeflowRuntimeState(messages) {
|
|
687
|
+
return (Array.isArray(messages) ? messages : []).filter(
|
|
688
|
+
(message) =>
|
|
689
|
+
message?.customType !== FREEFLOW_RUNTIME_STATE_MESSAGE_TYPE &&
|
|
690
|
+
message?.customType !== COGNITIVE_ROUTING_RUNTIME_STATE_MESSAGE_TYPE,
|
|
691
|
+
);
|
|
692
|
+
}
|
|
693
|
+
export function withFreeflowRuntimeState(messages, modeState, capabilityState, cognitiveRoutingRuntime = undefined) {
|
|
694
|
+
return [
|
|
695
|
+
...withoutFreeflowRuntimeState(messages),
|
|
696
|
+
freeflowRuntimeStateMessage(modeState, capabilityState, cognitiveRoutingRuntime),
|
|
697
|
+
];
|
|
698
|
+
}
|
|
699
|
+
export function runtimeContext(freeflowContext, capabilityState) {
|
|
700
|
+
if (capabilityState?.configured !== true || capabilityState?.enabled !== true || !freeflowContext?.corePrompt) {
|
|
643
701
|
return "";
|
|
644
702
|
}
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
return `# Freeflow Runtime Context
|
|
664
|
-
|
|
665
|
-
Freeflow Pi extension loaded this before the agent turn.
|
|
666
|
-
Runtime delivery: confirmed for this Pi \`before_agent_start\` invocation.
|
|
667
|
-
These instructions are context-loading only. They do not override user instructions, repo instructions, or host safety and approval policy.
|
|
668
|
-
|
|
669
|
-
${modeText}
|
|
670
|
-
|
|
671
|
-
${capabilityContext(capabilityState)}${interactionContractText}${routerText}
|
|
672
|
-
|
|
673
|
-
This Pi extension loads enabled runtime context before every agent turn and routes commands only; it does not enforce policy, block tools, grant permissions, or create repo-local hooks.`;
|
|
703
|
+
const blocks = [];
|
|
704
|
+
if (freeflowContext?.corePrompt) blocks.push(freeflowContext.corePrompt.trim());
|
|
705
|
+
if (capabilityState.interactionContract?.effective === true && freeflowContext?.interactionContractPrompt) {
|
|
706
|
+
blocks.push(freeflowContext.interactionContractPrompt.trim());
|
|
707
|
+
}
|
|
708
|
+
if (capabilityState.skills?.effective === true && freeflowContext?.skillsPrompt) {
|
|
709
|
+
blocks.push(freeflowContext.skillsPrompt.trim());
|
|
710
|
+
}
|
|
711
|
+
if (capabilityState.cognitiveRouting?.effective === true && freeflowContext?.cognitiveRoutingPrompt) {
|
|
712
|
+
blocks.push(freeflowContext.cognitiveRoutingPrompt.trim());
|
|
713
|
+
}
|
|
714
|
+
if (capabilityState.contextVirtualization?.effective === true && freeflowContext?.contextVirtualizationPrompt) {
|
|
715
|
+
blocks.push(freeflowContext.contextVirtualizationPrompt.trim());
|
|
716
|
+
}
|
|
717
|
+
if (capabilityState.conversationHistory?.effective === true && freeflowContext?.conversationHistoryPrompt) {
|
|
718
|
+
blocks.push(freeflowContext.conversationHistoryPrompt.trim());
|
|
719
|
+
}
|
|
720
|
+
return blocks.filter(Boolean).join("\n\n");
|
|
674
721
|
}
|
|
675
722
|
export async function setSessionCoreOverride(key, value, ctx, pi) {
|
|
676
723
|
if (!SESSION_CORE_KEYS.has(key)) {
|
|
@@ -695,7 +742,7 @@ export async function setSessionCoreOverride(key, value, ctx, pi) {
|
|
|
695
742
|
changed: true,
|
|
696
743
|
reloadRequired: key === "enabled" || key === "skillsEnabled",
|
|
697
744
|
sessionOverrides: { ...currentSessionOverrides },
|
|
698
|
-
capabilityState: await readCapabilityState(ctx.cwd),
|
|
745
|
+
capabilityState: await readCapabilityState(ctx.cwd, ctx, pi?.host),
|
|
699
746
|
};
|
|
700
747
|
}
|
|
701
748
|
export async function resetSessionOverrides(ctx, pi) {
|
|
@@ -728,7 +775,7 @@ export async function setSessionMode(mode, ctx, pi) {
|
|
|
728
775
|
}
|
|
729
776
|
export async function handleModeCommand(args, ctx, pi) {
|
|
730
777
|
const arg = args?.trim();
|
|
731
|
-
const capabilityState = await readCapabilityState(ctx.cwd);
|
|
778
|
+
const capabilityState = await readCapabilityState(ctx.cwd, ctx, pi?.host);
|
|
732
779
|
const inactiveModeState = await readModeState(ctx.cwd);
|
|
733
780
|
if (!capabilityState.configured) {
|
|
734
781
|
setModeStatus(ctx, inactiveModeState, capabilityState);
|