diff --git a/.gitignore b/.gitignore index d70ca94..e5a4825 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,4 @@ __pycache__ .idea/ build/ dist/ +.ailly_iam_policy diff --git a/aws_doc_sdk_examples_tools/agent/README.md b/aws_doc_sdk_examples_tools/agent/README.md index 330d21e..6955f13 100644 --- a/aws_doc_sdk_examples_tools/agent/README.md +++ b/aws_doc_sdk_examples_tools/agent/README.md @@ -36,7 +36,11 @@ python -m aws_doc_sdk_examples_tools.agent.bin.main \ ### 🔧 Arguments -Run `python -m aws_doc_sdk_examples_tools.agent.bin.main --help` for more info. +- `iam_tributary_root`: Path to the root directory of your IAM policy tributary +- `--system-prompts`: List of system prompt files or strings to include in the Ailly configuration +- `--skip-generation`: Skip the prompt generation and Ailly execution steps (useful for reprocessing existing outputs) + +Run `python -m aws_doc_sdk_examples_tools.agent.bin.main update --help` for more info. --- diff --git a/aws_doc_sdk_examples_tools/agent/bin/main.py b/aws_doc_sdk_examples_tools/agent/bin/main.py index 1e4baf3..e363289 100644 --- a/aws_doc_sdk_examples_tools/agent/bin/main.py +++ b/aws_doc_sdk_examples_tools/agent/bin/main.py @@ -17,18 +17,24 @@ @app.command() -def update(iam_tributary_root: str, system_prompts: List[str] = []) -> None: +def update( + iam_tributary_root: str, + system_prompts: List[str] = [], + skip_generation: bool = False, +) -> None: """ Generate new IAM policy metadata for a tributary. """ doc_gen_root = Path(iam_tributary_root) - make_prompts( - doc_gen_root=doc_gen_root, - system_prompts=system_prompts, - out_dir=AILLY_DIR_PATH, - language="IAMPolicyGrammar", - ) - run(["npx", "@ailly/cli", "--root", AILLY_DIR]) + + if not skip_generation: + make_prompts( + doc_gen_root=doc_gen_root, + system_prompts=system_prompts, + out_dir=AILLY_DIR_PATH, + language="IAMPolicyGrammar", + ) + run(["npx @ailly/cli@1.7.0-rc1", "--root", AILLY_DIR]) process_ailly_files( input_dir=str(AILLY_DIR_PATH), output_file=str(IAM_UPDATES_PATH) diff --git a/aws_doc_sdk_examples_tools/agent/make_prompts.py b/aws_doc_sdk_examples_tools/agent/make_prompts.py index 82832c1..b0333da 100644 --- a/aws_doc_sdk_examples_tools/agent/make_prompts.py +++ b/aws_doc_sdk_examples_tools/agent/make_prompts.py @@ -4,6 +4,7 @@ import os from pathlib import Path from typing import List +import yaml from aws_doc_sdk_examples_tools.doc_gen import DocGen, Snippet @@ -26,8 +27,9 @@ def write_prompts(doc_gen: DocGen, out_dir: Path, language: str) -> None: examples = doc_gen.examples snippets = doc_gen.snippets for example_id, example in examples.items(): - # "Title" and "Abbrev" are the defaults. If they're not there, it suggests we've already - # added new titles. + # TCXContentAnalyzer prefixes new metadata title/title_abbrev entries with + # the DEFAULT_METADATA_PREFIX. Checking this here to make sure we're only + # running the LLM tool on new extractions. title = example.title or "" title_abbrev = example.title_abbrev or "" if title.startswith(DEFAULT_METADATA_PREFIX) and title_abbrev.startswith( @@ -48,8 +50,17 @@ def write_prompts(doc_gen: DocGen, out_dir: Path, language: str) -> None: def setup_ailly(system_prompts: List[str], out_dir: Path) -> None: """Create the .aillyrc configuration file.""" fence = "---" - options = {"isolated": "true"} - options_block = "\n".join(f"{key}: {value}" for key, value in options.items()) + options = { + "isolated": "true", + "mcp": { + "awslabs.aws-documentation-mcp-server": { + "type": "stdio", + "command": "uvx", + "args": ["awslabs.aws-documentation-mcp-server@latest"], + } + }, + } + options_block = yaml.dump(options).strip() prompts_block = "\n".join(system_prompts) content = f"{fence}\n{options_block}\n{fence}\n{prompts_block}" diff --git a/aws_doc_sdk_examples_tools/agent/policy.json.example.md b/aws_doc_sdk_examples_tools/agent/policy.json.example.md deleted file mode 100644 index da7a414..0000000 --- a/aws_doc_sdk_examples_tools/agent/policy.json.example.md +++ /dev/null @@ -1,20 +0,0 @@ -# Example generated IAM policy descriptions -``` -[ - { - "title": "Allows Amazon SNS to send messages to an Amazon SQS dead-letter queue", - "title_abbrev": "Allows SNS to SQS messages", - "description": "This resource-based policy allows Amazon SNS to send messages to a specific Amazon SQS dead-letter queue. The policy grants the SNS service principal permission to perform the SQS:SendMessage action on the queue named [MyDeadLetterQueue], but only when the source ARN matches the specified SNS topic [MyTopic]. This policy would be attached to the SQS queue to enable it to receive messages from the SNS topic when message delivery fails. Replace [us-east-2] with your specific AWS Region." - }, - { - "title": "Allows managing log delivery and related resources", - "title_abbrev": "Allows log delivery management", - "description": "This identity-based policy allows managing CloudWatch Logs delivery configurations and related resources. The policy grants permissions to create, get, update, delete, and list log deliveries, as well as manage resource policies for a specific log group [SampleLogGroupName]. It also allows creating service-linked roles, tagging Firehose delivery streams, and managing bucket policies for a specific S3 bucket [bucket-name]. Replace [region] and [account-id] with your specific AWS Region and account ID, and [bucket-name] with your actual S3 bucket name." - }, - { - "title": "Allows Amazon SNS to send messages to an SQS dead-letter queue", - "title_abbrev": "SNS to SQS permissions", - "description": "This resource-based policy allows Amazon SNS to send messages to a specific Amazon SQS queue that serves as a dead-letter queue. The policy grants the SNS service permission to perform the SQS:SendMessage action on the queue named [MyDeadLetterQueue] in the [us-east-2] Region. The policy includes a condition that restricts this permission to messages originating from the SNS topic named [MyTopic] in the same Region and account." - } -] -``` \ No newline at end of file diff --git a/aws_doc_sdk_examples_tools/agent/process_ailly_files.py b/aws_doc_sdk_examples_tools/agent/process_ailly_files.py index b6c9b17..c4a703a 100644 --- a/aws_doc_sdk_examples_tools/agent/process_ailly_files.py +++ b/aws_doc_sdk_examples_tools/agent/process_ailly_files.py @@ -15,10 +15,7 @@ logger = logging.getLogger(__name__) EXPECTED_KEYS: Set[str] = set(["title", "title_abbrev"]) -VALUE_PREFIXES: Dict[str, str] = { - "title": "Example policy: ", - "title_abbrev": "Example: ", -} +VALUE_PREFIXES: Dict[str, str] = {"title": "", "title_abbrev": "", "synopsis": ""} class MissingExpectedKeys(Exception): @@ -84,6 +81,7 @@ def parse_ailly_file( if key in result: result[key] = f"{prefix}{result[key]}" + result["title_abbrev"] = result["title"] result["id"] = Path(file_path).name.split(".md.ailly.md")[0] result["_source_file"] = file_path diff --git a/requirements.txt b/requirements.txt index c8ef378..b8439f3 100644 --- a/requirements.txt +++ b/requirements.txt @@ -9,3 +9,4 @@ requests==2.32.0 types-PyYAML==6.0.12.12 yamale==4.0.4 typer==0.15.3 +uv==0.7.10