-
Notifications
You must be signed in to change notification settings - Fork 28
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add AI-powered policy builder and testing environment
Related to #9 Implement an AI-powered policy builder and testing environment in the Permit CLI. * **New Commands**: - Add `permit playground build` command for interactive policy creation with AI suggestions. - Add `permit playground test` command for real-time policy testing and evaluation logs. * **Documentation**: - Update `README.md` to include new commands and their usage. - Describe the new AI-powered policy builder and testing environment features. * **Dependencies**: - Update `package.json` to include dependencies for AI-powered features. - Add scripts for building and testing the new features. * **Command Implementations**: - Create `source/commands/playground/build.tsx` to implement the `permit playground build` command. - Create `source/commands/playground/test.tsx` to implement the `permit playground test` command. * **Command Index**: - Update `source/commands/index.tsx` to include entries for the new `permit playground build` and `permit playground test` commands.
- Loading branch information
1 parent
2b51a74
commit bf6edc4
Showing
5 changed files
with
184 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -13,7 +13,9 @@ | |
"build": "tsc", | ||
"dev": " NODE_NO_WARNINGS=1 tsc --watch", | ||
"test": "prettier --check ./source && npx tsx --test test*.tsx", | ||
"simple-check": "npx tsx ./source/cli.tsx pdp check -u [email protected] -a create -r task" | ||
"simple-check": "npx tsx ./source/cli.tsx pdp check -u [email protected] -a create -r task", | ||
"playground-build": "npx tsx ./source/cli.tsx playground build", | ||
"playground-test": "npx tsx ./source/cli.tsx playground test" | ||
}, | ||
"files": [ | ||
"dist" | ||
|
@@ -31,7 +33,8 @@ | |
"pastel": "^3.0.0", | ||
"permitio": "^2.7.2", | ||
"react": "^18.2.0", | ||
"zod": "^3.21.4" | ||
"zod": "^3.21.4", | ||
"openai": "^3.1.0" | ||
}, | ||
"devDependencies": { | ||
"@sindresorhus/tsconfig": "^3.0.1", | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
import React, { useState, useEffect } from 'react'; | ||
import { Text, Box, Newline } from 'ink'; | ||
import SelectInput from 'ink-select-input'; | ||
import Spinner from 'ink-spinner'; | ||
import { type infer as zInfer, object, string } from 'zod'; | ||
import { option } from 'pastel'; | ||
import { apiCall } from '../../lib/api.js'; | ||
import { AuthProvider, useAuth } from '../../components/AuthProvider.js'; | ||
|
||
export const options = object({ | ||
key: string() | ||
.optional() | ||
.describe( | ||
option({ | ||
description: 'Use API key instead of user authentication', | ||
alias: 'k', | ||
}), | ||
), | ||
workspace: string() | ||
.optional() | ||
.describe( | ||
option({ | ||
description: 'Use predefined workspace to Login', | ||
}), | ||
), | ||
}); | ||
|
||
type Props = { | ||
readonly options: zInfer<typeof options>; | ||
}; | ||
|
||
export default function Build({ options: { key, workspace } }: Props) { | ||
const { authToken, loading, error } = useAuth(); | ||
const [policies, setPolicies] = useState([]); | ||
const [selectedPolicy, setSelectedPolicy] = useState(null); | ||
const [state, setState] = useState<'loading' | 'selecting' | 'done'>('loading'); | ||
|
||
useEffect(() => { | ||
const fetchPolicies = async () => { | ||
const { response } = await apiCall('v2/policies', authToken ?? ''); | ||
setPolicies(response); | ||
setState('selecting'); | ||
}; | ||
|
||
if (authToken) { | ||
fetchPolicies(); | ||
} | ||
}, [authToken]); | ||
|
||
const handleSelect = (item: any) => { | ||
setSelectedPolicy(item); | ||
setState('done'); | ||
}; | ||
|
||
return ( | ||
<AuthProvider> | ||
{loading && <Spinner type="dots" />} | ||
{error && <Text color="red">{error}</Text>} | ||
{state === 'selecting' && ( | ||
<> | ||
<Text>Select a policy to build:</Text> | ||
<SelectInput items={policies.map((policy: any) => ({ label: policy.name, value: policy }))} onSelect={handleSelect} /> | ||
</> | ||
)} | ||
{state === 'done' && selectedPolicy && ( | ||
<Box flexDirection="column"> | ||
<Text>Selected Policy: {selectedPolicy.label}</Text> | ||
<Newline /> | ||
<Text>Building policy...</Text> | ||
{/* Add AI suggestions and policy building logic here */} | ||
</Box> | ||
)} | ||
</AuthProvider> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
import React, { useState, useEffect } from 'react'; | ||
import { Text, Box, Newline } from 'ink'; | ||
import SelectInput from 'ink-select-input'; | ||
import Spinner from 'ink-spinner'; | ||
import { type infer as zInfer, object, string } from 'zod'; | ||
import { option } from 'pastel'; | ||
import { apiCall } from '../../lib/api.js'; | ||
import { AuthProvider, useAuth } from '../../components/AuthProvider.js'; | ||
|
||
export const options = object({ | ||
key: string() | ||
.optional() | ||
.describe( | ||
option({ | ||
description: 'Use API key instead of user authentication', | ||
alias: 'k', | ||
}), | ||
), | ||
workspace: string() | ||
.optional() | ||
.describe( | ||
option({ | ||
description: 'Use predefined workspace to Login', | ||
}), | ||
), | ||
}); | ||
|
||
type Props = { | ||
readonly options: zInfer<typeof options>; | ||
}; | ||
|
||
export default function Test({ options: { key, workspace } }: Props) { | ||
const { authToken, loading, error } = useAuth(); | ||
const [policies, setPolicies] = useState([]); | ||
const [selectedPolicy, setSelectedPolicy] = useState(null); | ||
const [testResults, setTestResults] = useState(null); | ||
const [state, setState] = useState<'loading' | 'selecting' | 'testing' | 'done'>('loading'); | ||
|
||
useEffect(() => { | ||
const fetchPolicies = async () => { | ||
const { response } = await apiCall('v2/policies', authToken ?? ''); | ||
setPolicies(response); | ||
setState('selecting'); | ||
}; | ||
|
||
if (authToken) { | ||
fetchPolicies(); | ||
} | ||
}, [authToken]); | ||
|
||
const handleSelect = async (item: any) => { | ||
setSelectedPolicy(item); | ||
setState('testing'); | ||
const { response } = await apiCall(`v2/policies/${item.value}/test`, authToken ?? ''); | ||
setTestResults(response); | ||
setState('done'); | ||
}; | ||
|
||
return ( | ||
<AuthProvider> | ||
{loading && <Spinner type="dots" />} | ||
{error && <Text color="red">{error}</Text>} | ||
{state === 'selecting' && ( | ||
<> | ||
<Text>Select a policy to test:</Text> | ||
<SelectInput items={policies.map((policy: any) => ({ label: policy.name, value: policy }))} onSelect={handleSelect} /> | ||
</> | ||
)} | ||
{state === 'testing' && ( | ||
<Box flexDirection="column"> | ||
<Text>Testing policy...</Text> | ||
<Spinner type="dots" /> | ||
</Box> | ||
)} | ||
{state === 'done' && testResults && ( | ||
<Box flexDirection="column"> | ||
<Text>Test Results:</Text> | ||
<Newline /> | ||
<Text>{JSON.stringify(testResults, null, 2)}</Text> | ||
</Box> | ||
)} | ||
</AuthProvider> | ||
); | ||
} |