@hassangameryt/freeflow 0.2.0 → 0.4.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/.agents/plugins/marketplace.json +1 -1
- package/.claude-plugin/marketplace.json +4 -4
- package/{plugins/freeflow/.claude-plugin → .claude-plugin}/plugin.json +5 -2
- package/{plugins/freeflow/.codex-plugin → .codex-plugin}/plugin.json +8 -9
- package/README.md +194 -127
- package/assets/feedback-loop.png +0 -0
- package/assets/freeflow-plugin-icon.png +0 -0
- package/assets/freeflow_workflow_map.png +0 -0
- package/assets/workflow.png +0 -0
- package/command-surface.json +129 -0
- package/hooks/freeflow-runtime-context.mjs +419 -0
- package/hooks/tests/check-runtime-context-hook.sh +223 -0
- package/package.json +41 -22
- package/pi-extension/dist/index.js +269 -0
- package/pi-extension/dist/integrations/mcp-config.js +29 -0
- package/pi-extension/dist/output-router/host-producer-identification.js +232 -0
- package/pi-extension/dist/output-router/native-safety-net.js +216 -0
- package/pi-extension/dist/output-router/observed-tool-routing.js +122 -0
- package/pi-extension/dist/output-router/renderers.js +1023 -0
- package/pi-extension/dist/output-router/router-tools.js +554 -0
- package/pi-extension/dist/output-router/schemas.js +383 -0
- package/pi-extension/dist/output-router/status.js +744 -0
- package/pi-extension/dist/output-router/utils.js +502 -0
- package/pi-extension/dist/runtime/runtime-context.js +798 -0
- package/pi-extension/dist/settings/settings-tui.js +314 -0
- package/pi-extension/dist/settings/settings-ui.js +1487 -0
- package/pi-extension/freeflow/index.js +1 -0
- package/pi-extension/src/index.ts +295 -0
- package/pi-extension/src/integrations/mcp-config.ts +32 -0
- package/pi-extension/src/output-router/host-producer-identification.ts +256 -0
- package/pi-extension/src/output-router/native-safety-net.ts +248 -0
- package/pi-extension/src/output-router/observed-tool-routing.ts +134 -0
- package/pi-extension/src/output-router/renderers.ts +1108 -0
- package/pi-extension/src/output-router/router-tools.ts +579 -0
- package/pi-extension/src/output-router/schemas.ts +387 -0
- package/pi-extension/src/output-router/status.ts +791 -0
- package/pi-extension/src/output-router/utils.ts +554 -0
- package/pi-extension/src/runtime/runtime-context.ts +895 -0
- package/pi-extension/src/settings/settings-tui.ts +408 -0
- package/pi-extension/src/settings/settings-ui.ts +1730 -0
- package/pi-extension/tests/integration/pi-extension.test.js +4018 -0
- package/pi-extension/tests/output-router/observed-producers.test.js +132 -0
- package/pi-extension/tests/output-router/search.test.js +722 -0
- package/pi-extension/tests/settings/settings-tui.test.js +243 -0
- package/pi-extension/tsconfig.json +16 -0
- package/{plugins/freeflow/router/dist → router/dist/benchmarks}/benchmark-harness.d.ts +16 -13
- package/router/dist/benchmarks/benchmark-harness.js +92 -0
- package/router/dist/benchmarks/benchmarks.d.ts +109 -0
- package/router/dist/benchmarks/benchmarks.js +979 -0
- package/router/dist/benchmarks/codex-qa-benchmarks.d.ts +95 -0
- package/router/dist/benchmarks/codex-qa-benchmarks.js +500 -0
- package/router/dist/benchmarks/command-benchmarks.d.ts +143 -0
- package/router/dist/benchmarks/command-benchmarks.js +698 -0
- package/router/dist/benchmarks/context-mode-normalized-benchmarks.d.ts +82 -0
- package/router/dist/benchmarks/context-mode-normalized-benchmarks.js +773 -0
- package/router/dist/benchmarks/context-mode-real-deep-benchmark.d.ts +132 -0
- package/router/dist/benchmarks/context-mode-real-deep-benchmark.js +1380 -0
- package/router/dist/benchmarks/context-saving-baseline.d.ts +60 -0
- package/router/dist/benchmarks/context-saving-baseline.js +470 -0
- package/router/dist/benchmarks/index-benchmarks.d.ts +103 -0
- package/router/dist/benchmarks/index-benchmarks.js +862 -0
- package/router/dist/benchmarks/storage-policy-benchmarks.d.ts +101 -0
- package/router/dist/benchmarks/storage-policy-benchmarks.js +618 -0
- package/router/dist/benchmarks/vault-index-benchmarks.d.ts +56 -0
- package/router/dist/benchmarks/vault-index-benchmarks.js +322 -0
- package/router/dist/config/config.d.ts +103 -0
- package/router/dist/config/config.js +632 -0
- package/{plugins/freeflow/router/dist → router/dist/config}/router-contract.d.ts +2 -2
- package/router/dist/config/router-contract.js +54 -0
- package/{plugins/freeflow/router/dist → router/dist/config}/schema.d.ts +19 -10
- package/router/dist/config/schema.js +648 -0
- package/router/dist/config/types.d.ts +573 -0
- package/router/dist/config/types.js +41 -0
- package/router/dist/evidence/bounded-evidence.d.ts +40 -0
- package/router/dist/evidence/bounded-evidence.js +323 -0
- package/router/dist/evidence/evidence-range-selector.d.ts +24 -0
- package/router/dist/evidence/evidence-range-selector.js +232 -0
- package/router/dist/evidence/evidence-search.d.ts +27 -0
- package/router/dist/evidence/evidence-search.js +490 -0
- package/{plugins/freeflow/router/dist → router/dist/evidence}/evidence.d.ts +18 -18
- package/router/dist/evidence/evidence.js +200 -0
- package/router/dist/evidence/failure-contracts.d.ts +37 -0
- package/router/dist/evidence/failure-contracts.js +166 -0
- package/router/dist/evidence/line-ranges.d.ts +24 -0
- package/router/dist/evidence/line-ranges.js +22 -0
- package/router/dist/experiments/local-index.d.ts +64 -0
- package/router/dist/experiments/local-index.js +581 -0
- package/router/dist/index.d.ts +30 -0
- package/router/dist/index.js +32 -0
- package/router/dist/local/local-traversal.d.ts +18 -0
- package/router/dist/local/local-traversal.js +334 -0
- package/router/dist/processing/engine.d.ts +132 -0
- package/router/dist/processing/engine.js +533 -0
- package/router/dist/processing/reducers.d.ts +280 -0
- package/router/dist/processing/reducers.js +1673 -0
- package/router/dist/processing/renderers.d.ts +31 -0
- package/router/dist/processing/renderers.js +195 -0
- package/router/dist/processing/scripts.d.ts +91 -0
- package/router/dist/processing/scripts.js +386 -0
- package/{plugins/freeflow/router/dist → router/dist/repo}/repo-traversal.d.ts +9 -9
- package/router/dist/repo/repo-traversal.js +245 -0
- package/router/dist/routing/observed-reducers.d.ts +41 -0
- package/router/dist/routing/observed-reducers.js +661 -0
- package/router/dist/routing/observed-routing.d.ts +26 -0
- package/router/dist/routing/observed-routing.js +378 -0
- package/router/dist/routing/parsers.d.ts +16 -0
- package/router/dist/routing/parsers.js +521 -0
- package/router/dist/routing/run-filters.d.ts +60 -0
- package/router/dist/routing/run-filters.js +238 -0
- package/router/dist/routing/run-reducers.d.ts +49 -0
- package/router/dist/routing/run-reducers.js +122 -0
- package/router/dist/sandbox/adapter-roots.d.ts +46 -0
- package/router/dist/sandbox/adapter-roots.js +66 -0
- package/router/dist/sandbox/eryx-python-adapter.d.ts +13 -0
- package/router/dist/sandbox/eryx-python-adapter.js +868 -0
- package/router/dist/sandbox/jq-wasm-adapter.d.ts +9 -0
- package/router/dist/sandbox/jq-wasm-adapter.js +429 -0
- package/router/dist/sandbox/quickjs-wasi-adapter.d.ts +13 -0
- package/router/dist/sandbox/quickjs-wasi-adapter.js +384 -0
- package/router/dist/sandbox/script-sandbox.d.ts +134 -0
- package/router/dist/sandbox/script-sandbox.js +337 -0
- package/router/dist/setup/script-transform-adapters.d.ts +32 -0
- package/router/dist/setup/script-transform-adapters.js +278 -0
- package/router/dist/tools/batch.d.ts +33 -0
- package/router/dist/tools/batch.js +586 -0
- package/router/dist/tools/run.d.ts +62 -0
- package/router/dist/tools/run.js +1304 -0
- package/router/dist/tools/search.d.ts +66 -0
- package/router/dist/tools/search.js +1364 -0
- package/router/dist/transform/engine.d.ts +168 -0
- package/router/dist/transform/engine.js +2072 -0
- package/router/dist/vault/vault-index.d.ts +125 -0
- package/router/dist/vault/vault-index.js +416 -0
- package/router/dist/vault/vault.d.ts +138 -0
- package/router/dist/vault/vault.js +630 -0
- package/runtime/interaction-contract.md +16 -0
- package/skills/bypass/SKILL.md +82 -0
- package/skills/commit-work/SKILL.md +106 -0
- package/skills/commit-work/references/staging-decisions.md +73 -0
- package/skills/decision-gate/SKILL.md +48 -0
- package/skills/design-for-depth/SKILL.md +106 -0
- package/skills/design-for-depth/references/design-pressure-signals.md +314 -0
- package/skills/design-for-depth/references/interface-design-loop.md +156 -0
- package/skills/design-for-depth/references/software-design-philosophy.md +248 -0
- package/skills/diagnose-failure/SKILL.md +105 -0
- package/skills/diagnose-failure/references/diagnostic-loop-catalog.md +36 -0
- package/skills/diagnose-failure/references/flaky-and-performance.md +43 -0
- package/skills/discuss/SKILL.md +121 -0
- package/skills/discuss/references/checkpoints.md +66 -0
- package/skills/evaluate-skill/SKILL.md +105 -0
- package/skills/evaluate-skill/references/definition-schema.md +345 -0
- package/skills/evaluate-skill/references/evaluation-design.md +86 -0
- package/skills/evaluate-skill/references/execution-and-evidence.md +85 -0
- package/skills/evaluate-skill/references/review-and-revision.md +51 -0
- package/skills/evaluate-skill/scripts/lib/definitions.mjs +296 -0
- package/skills/evaluate-skill/scripts/lib/evidence.mjs +46 -0
- package/skills/evaluate-skill/scripts/lib/grade-comparison.mjs +60 -0
- package/skills/evaluate-skill/scripts/lib/grade-interaction.mjs +148 -0
- package/skills/evaluate-skill/scripts/lib/grade-support.mjs +126 -0
- package/skills/evaluate-skill/scripts/lib/grade-workspace.mjs +192 -0
- package/skills/evaluate-skill/scripts/lib/grade.mjs +56 -0
- package/skills/evaluate-skill/scripts/lib/pi.mjs +489 -0
- package/skills/evaluate-skill/scripts/lib/process.mjs +79 -0
- package/skills/evaluate-skill/scripts/lib/rpc.mjs +444 -0
- package/skills/evaluate-skill/scripts/lib/runner.mjs +346 -0
- package/skills/evaluate-skill/scripts/lib/sandbox.mjs +409 -0
- package/skills/evaluate-skill/scripts/lib/view.mjs +337 -0
- package/skills/evaluate-skill/scripts/pi-guard.mjs +164 -0
- package/skills/evaluate-skill/scripts/skill-eval.mjs +101 -0
- package/skills/execute-work/SKILL.md +99 -0
- package/skills/execute-work/references/code-practices.md +78 -0
- package/skills/execute-work/references/execution-loop.md +77 -0
- package/skills/finish-branch/SKILL.md +117 -0
- package/skills/finish-branch/references/integration-options.md +80 -0
- package/skills/handoff/SKILL.md +92 -0
- package/skills/handoff/references/templates.md +141 -0
- package/skills/launch-work/SKILL.md +116 -0
- package/skills/launch-work/references/launch-readiness.md +85 -0
- package/skills/migration-work/SKILL.md +115 -0
- package/skills/migration-work/references/migration-lifecycle.md +82 -0
- package/skills/mode-contract/SKILL.md +82 -0
- package/skills/output-router/SKILL.md +206 -0
- package/skills/output-router/references/safety-policy.md +40 -0
- package/skills/release-work/SKILL.md +118 -0
- package/skills/release-work/references/release-evidence.md +78 -0
- package/skills/review-artifact/SKILL.md +126 -0
- package/skills/review-artifact/references/reviewer-prompt.md +148 -0
- package/skills/review-work/SKILL.md +126 -0
- package/skills/review-work/references/reviewer-prompt.md +134 -0
- package/skills/review-work/references/security-risk-lens.md +67 -0
- package/skills/setup-freeflow/SKILL.md +98 -0
- package/skills/setup-freeflow/references/activation-contract.md +120 -0
- package/skills/setup-freeflow/references/host-setup.md +72 -0
- package/skills/setup-freeflow/references/output-router-setup.md +110 -0
- package/skills/simplify-code/SKILL.md +80 -0
- package/skills/simplify-code/references/simplification-patterns.md +70 -0
- package/skills/tdd/SKILL.md +96 -0
- package/skills/tdd/references/test-design.md +96 -0
- package/skills/track-work/SKILL.md +84 -0
- package/skills/track-work/references/working-record-schema.md +378 -0
- package/skills/verify-work/SKILL.md +85 -0
- package/skills/verify-work/references/browser-runtime-evidence.md +55 -0
- package/skills/verify-work/references/integration-evidence.md +51 -0
- package/skills/verify-work/references/performance-evidence.md +57 -0
- package/skills/workflow/SKILL.md +91 -0
- package/skills/workflow/references/domain-skill-composition.md +57 -0
- package/skills/workflow/references/workflow-loop.md +92 -0
- package/skills/write-plan/SKILL.md +123 -0
- package/skills/write-plan/references/plan-shapes.md +156 -0
- package/skills/write-skill/SKILL.md +119 -0
- package/skills/write-skill/references/activation-boundaries.md +62 -0
- package/skills/write-skill/references/agent-first-instructions.md +87 -0
- package/skills/write-skill/references/progressive-disclosure.md +63 -0
- package/skills/write-skill/scripts/lib/skill-author.mjs +653 -0
- package/skills/write-skill/scripts/skill-author.mjs +104 -0
- package/skills/write-spec/SKILL.md +104 -0
- package/skills/write-spec/references/artifact-standards.md +86 -0
- package/skills/write-spec/references/decision-records.md +77 -0
- package/skills/write-spec/references/spec-shapes.md +128 -0
- package/plugins/freeflow/command-surface.json +0 -77
- package/plugins/freeflow/docs/README.md +0 -40
- package/plugins/freeflow/docs/adr/0001-three-modes.md +0 -27
- package/plugins/freeflow/docs/adr/0002-evals-before-hooks.md +0 -17
- package/plugins/freeflow/docs/adr/0003-release-boundary.md +0 -21
- package/plugins/freeflow/docs/adr/0004-research-replaces-shallow-discovery-skills.md +0 -26
- package/plugins/freeflow/docs/adr/README.md +0 -8
- package/plugins/freeflow/docs/architecture.md +0 -86
- package/plugins/freeflow/docs/output-router.md +0 -212
- package/plugins/freeflow/docs/release-evidence.md +0 -69
- package/plugins/freeflow/docs/skills.md +0 -43
- package/plugins/freeflow/docs/workflow.md +0 -57
- package/plugins/freeflow/hooks/freeflow-runtime-context.mjs +0 -257
- package/plugins/freeflow/pi-extension/index.js +0 -1176
- package/plugins/freeflow/router/dist/benchmark-harness.js +0 -92
- package/plugins/freeflow/router/dist/benchmarks.d.ts +0 -102
- package/plugins/freeflow/router/dist/benchmarks.js +0 -880
- package/plugins/freeflow/router/dist/bounded-evidence.d.ts +0 -40
- package/plugins/freeflow/router/dist/bounded-evidence.js +0 -310
- package/plugins/freeflow/router/dist/codex-qa-benchmarks.d.ts +0 -91
- package/plugins/freeflow/router/dist/codex-qa-benchmarks.js +0 -461
- package/plugins/freeflow/router/dist/command-benchmarks.d.ts +0 -128
- package/plugins/freeflow/router/dist/command-benchmarks.js +0 -652
- package/plugins/freeflow/router/dist/config.d.ts +0 -22
- package/plugins/freeflow/router/dist/config.js +0 -114
- package/plugins/freeflow/router/dist/evidence-range-selector.d.ts +0 -22
- package/plugins/freeflow/router/dist/evidence-range-selector.js +0 -180
- package/plugins/freeflow/router/dist/evidence-search.d.ts +0 -25
- package/plugins/freeflow/router/dist/evidence-search.js +0 -450
- package/plugins/freeflow/router/dist/evidence.js +0 -196
- package/plugins/freeflow/router/dist/experimental-local-index.d.ts +0 -1
- package/plugins/freeflow/router/dist/experimental-local-index.js +0 -1
- package/plugins/freeflow/router/dist/experiments/local-index.d.ts +0 -58
- package/plugins/freeflow/router/dist/experiments/local-index.js +0 -562
- package/plugins/freeflow/router/dist/index-benchmarks.d.ts +0 -84
- package/plugins/freeflow/router/dist/index-benchmarks.js +0 -458
- package/plugins/freeflow/router/dist/index.d.ts +0 -12
- package/plugins/freeflow/router/dist/index.js +0 -12
- package/plugins/freeflow/router/dist/line-ranges.d.ts +0 -22
- package/plugins/freeflow/router/dist/line-ranges.js +0 -22
- package/plugins/freeflow/router/dist/parsers.d.ts +0 -16
- package/plugins/freeflow/router/dist/parsers.js +0 -473
- package/plugins/freeflow/router/dist/repo-traversal.js +0 -242
- package/plugins/freeflow/router/dist/retrieve.d.ts +0 -33
- package/plugins/freeflow/router/dist/retrieve.js +0 -855
- package/plugins/freeflow/router/dist/router-contract.js +0 -54
- package/plugins/freeflow/router/dist/run.d.ts +0 -26
- package/plugins/freeflow/router/dist/run.js +0 -356
- package/plugins/freeflow/router/dist/schema.js +0 -354
- package/plugins/freeflow/router/dist/types.d.ts +0 -234
- package/plugins/freeflow/router/dist/types.js +0 -9
- package/plugins/freeflow/router/dist/vault.d.ts +0 -80
- package/plugins/freeflow/router/dist/vault.js +0 -484
- package/plugins/freeflow/skills/bypass/SKILL.md +0 -68
- package/plugins/freeflow/skills/commit-work/SKILL.md +0 -98
- package/plugins/freeflow/skills/commit-work/references/staging-decisions.md +0 -51
- package/plugins/freeflow/skills/diagnose-failure/SKILL.md +0 -95
- package/plugins/freeflow/skills/diagnose-failure/references/feedback-loop-catalog.md +0 -25
- package/plugins/freeflow/skills/diagnose-failure/references/flaky-and-performance.md +0 -31
- package/plugins/freeflow/skills/evaluate-skill/SKILL.md +0 -96
- package/plugins/freeflow/skills/evaluate-skill/references/eval-patterns.md +0 -41
- package/plugins/freeflow/skills/evaluate-skill/references/grading-priority.md +0 -33
- package/plugins/freeflow/skills/execute-plan/SKILL.md +0 -132
- package/plugins/freeflow/skills/execute-plan/references/execution-map.md +0 -122
- package/plugins/freeflow/skills/handoff/SKILL.md +0 -66
- package/plugins/freeflow/skills/handoff/references/templates.md +0 -64
- package/plugins/freeflow/skills/interview-gate/SKILL.md +0 -90
- package/plugins/freeflow/skills/mode-contract/SKILL.md +0 -79
- package/plugins/freeflow/skills/output-router/SKILL.md +0 -69
- package/plugins/freeflow/skills/output-router/references/safety-policy.md +0 -33
- package/plugins/freeflow/skills/research/ARTIFACT-DESTINATIONS.md +0 -58
- package/plugins/freeflow/skills/research/CHECKPOINTS.md +0 -74
- package/plugins/freeflow/skills/research/LANGUAGE.md +0 -61
- package/plugins/freeflow/skills/research/SKILL.md +0 -128
- package/plugins/freeflow/skills/review-artifact/SKILL.md +0 -115
- package/plugins/freeflow/skills/review-artifact/references/reviewer-prompt.md +0 -56
- package/plugins/freeflow/skills/review-work/SKILL.md +0 -96
- package/plugins/freeflow/skills/review-work/references/reviewer-prompt.md +0 -97
- package/plugins/freeflow/skills/setup-freeflow/SKILL.md +0 -94
- package/plugins/freeflow/skills/setup-freeflow/references/activation-contract.md +0 -99
- package/plugins/freeflow/skills/setup-freeflow/references/host-setup.md +0 -35
- package/plugins/freeflow/skills/setup-freeflow/references/output-router-setup.md +0 -52
- package/plugins/freeflow/skills/verify-work/SKILL.md +0 -62
- package/plugins/freeflow/skills/workflow/SKILL.md +0 -95
- package/plugins/freeflow/skills/workflow/references/workflow-map.md +0 -102
- package/plugins/freeflow/skills/write-plan/SKILL.md +0 -88
- package/plugins/freeflow/skills/write-plan/references/plan-shapes.md +0 -70
- package/plugins/freeflow/skills/write-skill/SKILL.md +0 -88
- package/plugins/freeflow/skills/write-spec/SKILL.md +0 -90
- package/plugins/freeflow/skills/write-spec/references/artifact-standards.md +0 -67
- package/plugins/freeflow/skills/write-spec/references/spec-shapes.md +0 -69
- /package/{plugins/freeflow/assets → assets}/freeflow-plugin-icon-transparent.png +0 -0
- /package/{plugins/freeflow/hooks → hooks}/hooks.json +0 -0
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
import { POST_TOOL_ROUTING_MODES } from "./types.js";
|
|
2
|
-
export function isValidPostToolRoutingMode(value) {
|
|
3
|
-
return typeof value === "string" && POST_TOOL_ROUTING_MODES.includes(value);
|
|
4
|
-
}
|
|
5
|
-
export function isNativeSafetyNetEnabled(value) {
|
|
6
|
-
return value === "safety-net" || value === "strict";
|
|
7
|
-
}
|
|
8
|
-
export function validatePositiveIntegerThreshold(value, path) {
|
|
9
|
-
if (typeof value === "number" && Number.isInteger(value) && Number.isFinite(value) && value > 0) {
|
|
10
|
-
return [];
|
|
11
|
-
}
|
|
12
|
-
return [{ path, message: "Expected a positive integer." }];
|
|
13
|
-
}
|
|
14
|
-
export function validateVaultRetentionPolicy(value, path) {
|
|
15
|
-
if (!isRecord(value)) {
|
|
16
|
-
return [{ path, message: "Expected retention policy object." }];
|
|
17
|
-
}
|
|
18
|
-
if (value.strategy === "manual") {
|
|
19
|
-
return [];
|
|
20
|
-
}
|
|
21
|
-
if (value.strategy === "ttl") {
|
|
22
|
-
const ttlIssues = validatePositiveIntegerThreshold(value.ttlDays, `${path}.ttlDays`);
|
|
23
|
-
return ttlIssues.length ? ttlIssues : [];
|
|
24
|
-
}
|
|
25
|
-
return [{ path: `${path}.strategy`, message: "Expected retention strategy manual or ttl." }];
|
|
26
|
-
}
|
|
27
|
-
export function validateNormalizedRouterHints(value, path) {
|
|
28
|
-
if (value === undefined) {
|
|
29
|
-
return [];
|
|
30
|
-
}
|
|
31
|
-
if (!isRecord(value)) {
|
|
32
|
-
return [{ path, message: "Expected hints object." }];
|
|
33
|
-
}
|
|
34
|
-
return [
|
|
35
|
-
...validateOptionalStringArray(value.generatedPathGlobs, `${path}.generatedPathGlobs`),
|
|
36
|
-
...validateOptionalStringArray(value.noisyCommandPatterns, `${path}.noisyCommandPatterns`),
|
|
37
|
-
];
|
|
38
|
-
}
|
|
39
|
-
function validateOptionalStringArray(value, path) {
|
|
40
|
-
if (value === undefined) {
|
|
41
|
-
return [];
|
|
42
|
-
}
|
|
43
|
-
if (!Array.isArray(value)) {
|
|
44
|
-
return [{ path, message: "Expected an array of non-empty strings." }];
|
|
45
|
-
}
|
|
46
|
-
const invalidIndex = value.findIndex((item) => typeof item !== "string" || item.length === 0);
|
|
47
|
-
if (invalidIndex !== -1) {
|
|
48
|
-
return [{ path: `${path}[${invalidIndex}]`, message: "Expected a non-empty string." }];
|
|
49
|
-
}
|
|
50
|
-
return [];
|
|
51
|
-
}
|
|
52
|
-
function isRecord(value) {
|
|
53
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
54
|
-
}
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import type { CommandRoutedResult, ExecutionStatus, PreserveMode, RouterThresholds, VaultRetentionPolicy } from "./types.js";
|
|
2
|
-
export interface HostCommandRunRequest {
|
|
3
|
-
command: string | readonly string[];
|
|
4
|
-
cwd?: string;
|
|
5
|
-
timeoutMs?: number;
|
|
6
|
-
}
|
|
7
|
-
export interface HostCommandRunResult {
|
|
8
|
-
stdout: string;
|
|
9
|
-
stderr: string;
|
|
10
|
-
executionStatus: ExecutionStatus;
|
|
11
|
-
exitCode: number | null;
|
|
12
|
-
combined?: string;
|
|
13
|
-
durationMs?: number;
|
|
14
|
-
}
|
|
15
|
-
export interface HostCommandRunner {
|
|
16
|
-
run(request: HostCommandRunRequest): Promise<HostCommandRunResult>;
|
|
17
|
-
}
|
|
18
|
-
export interface FreeflowRunOptions extends HostCommandRunRequest {
|
|
19
|
-
sessionId: string;
|
|
20
|
-
vaultRoot?: string;
|
|
21
|
-
vaultRetention?: VaultRetentionPolicy;
|
|
22
|
-
preserve?: PreserveMode;
|
|
23
|
-
goal?: string;
|
|
24
|
-
thresholds?: Partial<RouterThresholds>;
|
|
25
|
-
}
|
|
26
|
-
export declare function freeflowRun(options: FreeflowRunOptions, runner: HostCommandRunner): Promise<CommandRoutedResult>;
|
|
@@ -1,356 +0,0 @@
|
|
|
1
|
-
import { createHash } from "node:crypto";
|
|
2
|
-
import { commandOutputFingerprints, createVault, findExactDuplicateCommandOutput, storeCommandOutput, } from "./vault.js";
|
|
3
|
-
import { DEFAULT_ROUTER_THRESHOLDS } from "./config.js";
|
|
4
|
-
import { assembleTextEvidence, byteLength, countLines } from "./evidence.js";
|
|
5
|
-
import { parseCommandOutput } from "./parsers.js";
|
|
6
|
-
export async function freeflowRun(options, runner) {
|
|
7
|
-
const preserve = options.preserve ?? "important";
|
|
8
|
-
const thresholds = { ...DEFAULT_ROUTER_THRESHOLDS, ...options.thresholds };
|
|
9
|
-
const vaultOptions = {};
|
|
10
|
-
if (options.vaultRoot !== undefined) {
|
|
11
|
-
vaultOptions.root = options.vaultRoot;
|
|
12
|
-
}
|
|
13
|
-
if (options.vaultRetention !== undefined) {
|
|
14
|
-
vaultOptions.retention = options.vaultRetention;
|
|
15
|
-
}
|
|
16
|
-
const vault = createVault(vaultOptions);
|
|
17
|
-
let runResult;
|
|
18
|
-
try {
|
|
19
|
-
const runRequest = { command: options.command };
|
|
20
|
-
if (options.cwd !== undefined) {
|
|
21
|
-
runRequest.cwd = options.cwd;
|
|
22
|
-
}
|
|
23
|
-
if (options.timeoutMs !== undefined) {
|
|
24
|
-
runRequest.timeoutMs = options.timeoutMs;
|
|
25
|
-
}
|
|
26
|
-
runResult = await runner.run(runRequest);
|
|
27
|
-
}
|
|
28
|
-
catch (error) {
|
|
29
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
30
|
-
return {
|
|
31
|
-
toolStatus: "error",
|
|
32
|
-
decisionId: decisionId("run-error", commandText(options.command), message),
|
|
33
|
-
preserve,
|
|
34
|
-
outputId: "",
|
|
35
|
-
execution: { status: "failed", exitCode: null },
|
|
36
|
-
routing: {
|
|
37
|
-
status: "failed",
|
|
38
|
-
route: "run",
|
|
39
|
-
reason: `Adapter-provided runner failed before command output could be captured: ${message}`,
|
|
40
|
-
},
|
|
41
|
-
recovery: {
|
|
42
|
-
how: "No command output was captured. Retry through the host-approved runner or use the host-native shell tool if direct raw behavior is required.",
|
|
43
|
-
},
|
|
44
|
-
};
|
|
45
|
-
}
|
|
46
|
-
const combined = runResult.combined ?? combineOutputSections(runResult.stdout, runResult.stderr);
|
|
47
|
-
let record;
|
|
48
|
-
let duplicate;
|
|
49
|
-
const fingerprints = commandOutputFingerprints({
|
|
50
|
-
command: options.command,
|
|
51
|
-
stdout: runResult.stdout,
|
|
52
|
-
stderr: runResult.stderr,
|
|
53
|
-
combined,
|
|
54
|
-
executionStatus: runResult.executionStatus,
|
|
55
|
-
exitCode: runResult.exitCode,
|
|
56
|
-
...(options.cwd !== undefined ? { cwd: options.cwd } : {}),
|
|
57
|
-
});
|
|
58
|
-
if (preserve !== "full") {
|
|
59
|
-
try {
|
|
60
|
-
duplicate = await findExactDuplicateCommandOutput(vault, {
|
|
61
|
-
sessionId: options.sessionId,
|
|
62
|
-
fingerprints,
|
|
63
|
-
});
|
|
64
|
-
}
|
|
65
|
-
catch {
|
|
66
|
-
duplicate = undefined;
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
const execution = {
|
|
70
|
-
status: runResult.executionStatus,
|
|
71
|
-
exitCode: runResult.exitCode,
|
|
72
|
-
};
|
|
73
|
-
if (runResult.durationMs !== undefined) {
|
|
74
|
-
Object.assign(execution, { durationMs: runResult.durationMs });
|
|
75
|
-
}
|
|
76
|
-
try {
|
|
77
|
-
const storeOptions = {
|
|
78
|
-
sessionId: options.sessionId,
|
|
79
|
-
command: options.command,
|
|
80
|
-
stdout: runResult.stdout,
|
|
81
|
-
stderr: runResult.stderr,
|
|
82
|
-
combined,
|
|
83
|
-
executionStatus: runResult.executionStatus,
|
|
84
|
-
exitCode: runResult.exitCode,
|
|
85
|
-
decisionIds: [decisionId("run", commandText(options.command), options.sessionId)],
|
|
86
|
-
};
|
|
87
|
-
if (options.cwd !== undefined) {
|
|
88
|
-
Object.assign(storeOptions, { cwd: options.cwd });
|
|
89
|
-
}
|
|
90
|
-
if (runResult.durationMs !== undefined) {
|
|
91
|
-
Object.assign(storeOptions, { durationMs: runResult.durationMs });
|
|
92
|
-
}
|
|
93
|
-
record = await storeCommandOutput(vault, storeOptions);
|
|
94
|
-
const routeOptions = {
|
|
95
|
-
outputId: record.outputId,
|
|
96
|
-
command: options.command,
|
|
97
|
-
executionStatus: runResult.executionStatus,
|
|
98
|
-
exitCode: runResult.exitCode,
|
|
99
|
-
stdout: runResult.stdout,
|
|
100
|
-
stderr: runResult.stderr,
|
|
101
|
-
combined,
|
|
102
|
-
preserve,
|
|
103
|
-
thresholds,
|
|
104
|
-
};
|
|
105
|
-
if (options.goal !== undefined) {
|
|
106
|
-
routeOptions.goal = options.goal;
|
|
107
|
-
}
|
|
108
|
-
const routing = duplicate
|
|
109
|
-
? routeDuplicateCommandOutput({
|
|
110
|
-
outputId: record.outputId,
|
|
111
|
-
duplicate,
|
|
112
|
-
command: options.command,
|
|
113
|
-
executionStatus: runResult.executionStatus,
|
|
114
|
-
exitCode: runResult.exitCode,
|
|
115
|
-
})
|
|
116
|
-
: routeCommandOutput(routeOptions);
|
|
117
|
-
return {
|
|
118
|
-
toolStatus: "ok",
|
|
119
|
-
decisionId: routing.decisionId,
|
|
120
|
-
outputId: record.outputId,
|
|
121
|
-
preserve,
|
|
122
|
-
execution,
|
|
123
|
-
routing: {
|
|
124
|
-
status: routing.routingStatus,
|
|
125
|
-
route: "run",
|
|
126
|
-
reason: routing.reason,
|
|
127
|
-
},
|
|
128
|
-
summary: routing.summary,
|
|
129
|
-
importantLines: routing.importantLines,
|
|
130
|
-
parser: routing.parser,
|
|
131
|
-
recovery: commandRecoveryHint(record.outputId, duplicate),
|
|
132
|
-
};
|
|
133
|
-
}
|
|
134
|
-
catch (error) {
|
|
135
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
136
|
-
return commandRoutingFailureResult({
|
|
137
|
-
command: options.command,
|
|
138
|
-
outputId: record?.outputId ?? "",
|
|
139
|
-
preserve,
|
|
140
|
-
execution,
|
|
141
|
-
stdout: runResult.stdout,
|
|
142
|
-
stderr: runResult.stderr,
|
|
143
|
-
combined,
|
|
144
|
-
errorMessage: message,
|
|
145
|
-
});
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
function routeDuplicateCommandOutput(options) {
|
|
149
|
-
const currentVaultText = options.outputId === options.duplicate.outputId
|
|
150
|
-
? `Current run resolved to the same outputId=${options.outputId}.`
|
|
151
|
-
: `Current raw output was vaulted as outputId=${options.outputId}.`;
|
|
152
|
-
const statusText = `executionStatus=${options.executionStatus} exitCode=${options.exitCode}`;
|
|
153
|
-
return {
|
|
154
|
-
decisionId: decisionId("run-route", options.outputId, "exact-duplicate", options.duplicate.outputId),
|
|
155
|
-
routingStatus: "partial",
|
|
156
|
-
reason: `Exact duplicate command output matched previous outputId=${options.duplicate.outputId} by exact output hash and command/cwd/status fingerprint (${statusText}); returning a compact duplicate note instead of re-injecting repeated output. ${currentVaultText}`,
|
|
157
|
-
summary: `Command output is an exact duplicate of previous outputId=${options.duplicate.outputId}. ${currentVaultText}`,
|
|
158
|
-
importantLines: [],
|
|
159
|
-
parser: {
|
|
160
|
-
name: "duplicate-output",
|
|
161
|
-
confidence: 1,
|
|
162
|
-
fidelity: "exact",
|
|
163
|
-
compressed: true,
|
|
164
|
-
counts: { duplicateOutputs: 1 },
|
|
165
|
-
},
|
|
166
|
-
};
|
|
167
|
-
}
|
|
168
|
-
function commandRecoveryHint(outputId, duplicate) {
|
|
169
|
-
if (duplicate) {
|
|
170
|
-
return {
|
|
171
|
-
how: `Current exact command output: use freeflow_retrieve with source.kind=vault and outputId=${outputId}. Prior identical output: outputId=${duplicate.outputId}.`,
|
|
172
|
-
outputId,
|
|
173
|
-
};
|
|
174
|
-
}
|
|
175
|
-
return {
|
|
176
|
-
how: `Use freeflow_retrieve with source.kind=vault and outputId=${outputId} to recover exact command output.`,
|
|
177
|
-
outputId,
|
|
178
|
-
};
|
|
179
|
-
}
|
|
180
|
-
function commandRoutingFailureResult(options) {
|
|
181
|
-
const { stream, text } = routedCommandText({
|
|
182
|
-
outputId: options.outputId,
|
|
183
|
-
command: options.command,
|
|
184
|
-
executionStatus: options.execution.status,
|
|
185
|
-
exitCode: options.execution.exitCode,
|
|
186
|
-
stdout: options.stdout,
|
|
187
|
-
stderr: options.stderr,
|
|
188
|
-
combined: options.combined,
|
|
189
|
-
preserve: options.preserve,
|
|
190
|
-
thresholds: DEFAULT_ROUTER_THRESHOLDS,
|
|
191
|
-
});
|
|
192
|
-
const fallback = assembleTextEvidence({ stream, text });
|
|
193
|
-
const parser = {
|
|
194
|
-
name: "router-fallback",
|
|
195
|
-
confidence: 0,
|
|
196
|
-
fidelity: fallback.fidelity,
|
|
197
|
-
compressed: fallback.compressed,
|
|
198
|
-
};
|
|
199
|
-
const recovery = options.outputId
|
|
200
|
-
? {
|
|
201
|
-
how: `Routing failed after vault capture; use freeflow_retrieve with source.kind=vault and outputId=${options.outputId} to recover exact command output.`,
|
|
202
|
-
outputId: options.outputId,
|
|
203
|
-
}
|
|
204
|
-
: {
|
|
205
|
-
how: "Command output could not be vaulted. A bounded in-memory preview was returned; rerun through the host-approved runner if exact recovery is required.",
|
|
206
|
-
};
|
|
207
|
-
return {
|
|
208
|
-
toolStatus: "error",
|
|
209
|
-
decisionId: decisionId("run-route-error", commandText(options.command), options.errorMessage),
|
|
210
|
-
outputId: options.outputId,
|
|
211
|
-
preserve: options.preserve,
|
|
212
|
-
execution: options.execution,
|
|
213
|
-
routing: {
|
|
214
|
-
status: "failed",
|
|
215
|
-
route: "run",
|
|
216
|
-
reason: `Command executed, but Freeflow routing failed after execution: ${options.errorMessage}`,
|
|
217
|
-
},
|
|
218
|
-
summary: "Command executed, but Freeflow routing failed after execution.",
|
|
219
|
-
importantLines: fallback.importantLines,
|
|
220
|
-
parser,
|
|
221
|
-
recovery,
|
|
222
|
-
};
|
|
223
|
-
}
|
|
224
|
-
// Keep exactness-sensitive command routing aligned with
|
|
225
|
-
// plugins/freeflow/skills/output-router/references/safety-policy.md.
|
|
226
|
-
function routeCommandOutput(options) {
|
|
227
|
-
const outputBytes = byteLength(options.combined);
|
|
228
|
-
const outputLines = countLines(options.combined);
|
|
229
|
-
const isLarge = outputBytes > options.thresholds.largeOutputBytes || outputLines > options.thresholds.largeOutputLines;
|
|
230
|
-
const parseInput = {
|
|
231
|
-
command: options.command,
|
|
232
|
-
executionStatus: options.executionStatus,
|
|
233
|
-
exitCode: options.exitCode,
|
|
234
|
-
stdout: options.stdout,
|
|
235
|
-
stderr: options.stderr,
|
|
236
|
-
combined: options.combined,
|
|
237
|
-
};
|
|
238
|
-
if (options.goal !== undefined) {
|
|
239
|
-
Object.assign(parseInput, { goal: options.goal });
|
|
240
|
-
}
|
|
241
|
-
const parsed = parseCommandOutput(parseInput);
|
|
242
|
-
const parser = parsed.parser;
|
|
243
|
-
const statusText = `executionStatus=${options.executionStatus} exitCode=${options.exitCode}`;
|
|
244
|
-
const parserText = parserTextFor(parser);
|
|
245
|
-
if (options.preserve === "full") {
|
|
246
|
-
return routeFullOutput(options, parsed, outputBytes, outputLines, statusText);
|
|
247
|
-
}
|
|
248
|
-
if (options.executionStatus !== "success") {
|
|
249
|
-
return {
|
|
250
|
-
decisionId: decisionId("run-route", options.outputId, options.executionStatus, "failed", parser.name),
|
|
251
|
-
routingStatus: "routed",
|
|
252
|
-
reason: `Command failed or did not complete (${statusText}); selected failure evidence was returned and raw output was vaulted before routing (${parserText}).`,
|
|
253
|
-
summary: parsed.summary ?? `Command ${options.executionStatus} with exitCode=${options.exitCode}.`,
|
|
254
|
-
importantLines: parsed.importantLines,
|
|
255
|
-
parser,
|
|
256
|
-
};
|
|
257
|
-
}
|
|
258
|
-
if (isLarge) {
|
|
259
|
-
return {
|
|
260
|
-
decisionId: decisionId("run-route", options.outputId, "large-success", parser.name),
|
|
261
|
-
routingStatus: "partial",
|
|
262
|
-
reason: `Large successful command output (${outputBytes} bytes, ${outputLines} lines) was vaulted; bounded important lines were returned instead of full output (${parserText}).`,
|
|
263
|
-
summary: parsed.summary ?? `Command succeeded with ${outputLines} output lines and ${outputBytes} bytes.`,
|
|
264
|
-
importantLines: parsed.importantLines,
|
|
265
|
-
parser,
|
|
266
|
-
};
|
|
267
|
-
}
|
|
268
|
-
const nearRaw = selectNearRawSuccessfulLines(options);
|
|
269
|
-
const nearRawParser = parserWithEvidence(parser, nearRaw);
|
|
270
|
-
return {
|
|
271
|
-
decisionId: decisionId("run-route", options.outputId, "small-success", parser.name, nearRaw.fidelity),
|
|
272
|
-
routingStatus: nearRaw.fidelity === "exact" ? "routed" : "partial",
|
|
273
|
-
reason: `Small successful command output was captured in the vault and returned near-raw (${parserTextFor(nearRawParser)}).`,
|
|
274
|
-
summary: parsed.summary ?? `Command success with exitCode=${options.exitCode}.`,
|
|
275
|
-
importantLines: nearRaw.importantLines,
|
|
276
|
-
parser: nearRawParser,
|
|
277
|
-
};
|
|
278
|
-
}
|
|
279
|
-
function routeFullOutput(options, parsed, outputBytes, outputLines, statusText) {
|
|
280
|
-
const full = selectFullOutputLines(options);
|
|
281
|
-
const parser = parserWithEvidence(parsed.parser, full);
|
|
282
|
-
const routedStatus = full.fidelity === "exact" ? "routed" : "partial";
|
|
283
|
-
const capText = `${options.thresholds.largeOutputBytes} byte full-context cap`;
|
|
284
|
-
const reason = full.fidelity === "exact"
|
|
285
|
-
? `preserve=full returned exact command output within the ${capText} after raw output was vaulted (${statusText}; ${parserTextFor(parser)}).`
|
|
286
|
-
: `preserve=full output exceeded the bounded context policy (${outputBytes} bytes, ${outputLines} lines); a bounded preview was returned with raw vault recovery (${statusText}; ${parserTextFor(parser)}).`;
|
|
287
|
-
return {
|
|
288
|
-
decisionId: decisionId("run-route", options.outputId, "preserve-full", full.fidelity, parsed.parser.name),
|
|
289
|
-
routingStatus: routedStatus,
|
|
290
|
-
reason,
|
|
291
|
-
summary: parsed.summary ?? `Command ${options.executionStatus} with exitCode=${options.exitCode}.`,
|
|
292
|
-
importantLines: full.importantLines,
|
|
293
|
-
parser,
|
|
294
|
-
};
|
|
295
|
-
}
|
|
296
|
-
function selectNearRawSuccessfulLines(options) {
|
|
297
|
-
const { stream, text } = routedCommandText(options);
|
|
298
|
-
return assembleTextEvidence({
|
|
299
|
-
stream,
|
|
300
|
-
text,
|
|
301
|
-
caps: {
|
|
302
|
-
maxLines: options.thresholds.largeOutputLines,
|
|
303
|
-
maxExcerptBytes: options.thresholds.largeOutputBytes,
|
|
304
|
-
maxLineBytes: options.thresholds.largeOutputBytes,
|
|
305
|
-
},
|
|
306
|
-
});
|
|
307
|
-
}
|
|
308
|
-
function selectFullOutputLines(options) {
|
|
309
|
-
const { stream, text } = routedCommandText(options);
|
|
310
|
-
return assembleTextEvidence({
|
|
311
|
-
stream,
|
|
312
|
-
text,
|
|
313
|
-
caps: {
|
|
314
|
-
maxLines: Number.MAX_SAFE_INTEGER,
|
|
315
|
-
maxExcerptBytes: options.thresholds.largeOutputBytes,
|
|
316
|
-
maxLineBytes: options.thresholds.largeOutputBytes,
|
|
317
|
-
},
|
|
318
|
-
});
|
|
319
|
-
}
|
|
320
|
-
function routedCommandText(options) {
|
|
321
|
-
if (options.stdout.length > 0 && options.stderr.length === 0) {
|
|
322
|
-
return { stream: "stdout", text: options.stdout };
|
|
323
|
-
}
|
|
324
|
-
if (options.stderr.length > 0 && options.stdout.length === 0) {
|
|
325
|
-
return { stream: "stderr", text: options.stderr };
|
|
326
|
-
}
|
|
327
|
-
return { stream: "combined", text: options.combined };
|
|
328
|
-
}
|
|
329
|
-
function parserWithEvidence(parser, evidence) {
|
|
330
|
-
return {
|
|
331
|
-
...parser,
|
|
332
|
-
fidelity: parser.fidelity === "lossy" || evidence.fidelity === "lossy" ? "lossy" : "exact",
|
|
333
|
-
compressed: evidence.compressed,
|
|
334
|
-
};
|
|
335
|
-
}
|
|
336
|
-
function parserTextFor(parser) {
|
|
337
|
-
return `parser=${parser.name} confidence=${parser.confidence.toFixed(2)} fidelity=${parser.fidelity}`;
|
|
338
|
-
}
|
|
339
|
-
function combineOutputSections(stdout, stderr) {
|
|
340
|
-
if (stdout.length === 0) {
|
|
341
|
-
return stderr;
|
|
342
|
-
}
|
|
343
|
-
if (stderr.length === 0) {
|
|
344
|
-
return stdout;
|
|
345
|
-
}
|
|
346
|
-
return `[stdout]\n${stdout}\n[stderr]\n${stderr}`;
|
|
347
|
-
}
|
|
348
|
-
function commandText(command) {
|
|
349
|
-
return typeof command === "string" ? command : command.join(" ");
|
|
350
|
-
}
|
|
351
|
-
function decisionId(...parts) {
|
|
352
|
-
return `ffdec_${hash(parts.join("\0")).slice(0, 16)}`;
|
|
353
|
-
}
|
|
354
|
-
function hash(value) {
|
|
355
|
-
return createHash("sha256").update(value).digest("hex");
|
|
356
|
-
}
|