-
Notifications
You must be signed in to change notification settings - Fork 3.8k
[camera_android_camerax] Setup agent skills camerax #11930
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
ee20fa7
26b37ae
d825767
f7f0646
ea27e43
9ac31a2
87cfaf1
acbcc3e
7eabf5f
9e0d9e5
6b68664
0942453
9471107
c4e832f
acc34a5
288e5ec
43be3d1
8d17949
81c1c52
438537c
f64190b
14d7cfc
d7f024e
bc37ae6
16e3f28
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| # Ignore everything by default | ||
| * | ||
|
|
||
| # Un-ignore specific checked-in skills | ||
| # (Add specific contributor skills here as they are created) | ||
| !check-readiness/ | ||
| !check-readiness/SKILL.md | ||
| !check-readiness/scripts/ | ||
| !check-readiness/scripts/check.sh | ||
|
|
||
| # Keep essential configuration and docs | ||
| !.gitignore | ||
| !README.md | ||
| !ignore.json | ||
| !flutter_skills_ignore.json |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| # Agent Skills | ||
|
|
||
| This directory contains skills intended for repository maintainers and contributors. Local, checked-in skills are evaluated by `dart_skills_lint` and should be configured to prevent publishing to pub.dev. | ||
|
|
||
| **Note on Remotely Managed Skills:** | ||
| Skills that are remotely defined and managed using `npx skills` should **not** be installed directly into this directory. Instead, they must be installed into the repository root's `third_party/` directory to comply with third-party code policies. Once installed there, they should be symlinked into this directory. | ||
|
|
||
| Please see the `third_party/README.md` file at the root of the repository for specific rules and instructions on adding new remote skills. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| --- | ||
| name: check-readiness | ||
| description: Run this skill to check if the repository is ready for new work. Use this skill whenever the user asks to "check readiness", "see if we are ready to start work", or when starting a new task in the camera_android_camerax package. | ||
| metadata: | ||
| internal: true | ||
| --- | ||
| # Check Readiness | ||
|
|
||
| This skill verifies that the local environment is properly configured and clean before starting new work in the `camera_android_camerax` package. | ||
|
|
||
| ## Instructions | ||
| Run the bundled verification script ([scripts/check.sh](scripts/check.sh)) to perform the automated environment checks: | ||
| ```bash | ||
| bash .agents/skills/check-readiness/scripts/check.sh | ||
|
reidbaker marked this conversation as resolved.
|
||
| ``` | ||
|
|
||
| ### Handling the Results | ||
| 1. **If the script succeeds:** Inform the user that the environment is clean, dependencies are resolved, and it is ready for new work. | ||
| 2. **If the script fails:** Explain exactly which check failed (e.g., git is not clean, a symlink is broken, Flutter is missing from PATH) and offer to help resolve it. | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @camsim99 I have some work happening to turn this into dart code but if you are ok with it I would like to land that change independently.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,55 @@ | ||
| #!/bin/bash | ||
| # Copyright 2013 The Flutter Authors | ||
| # Use of this source code is governed by a BSD-style license that can be | ||
| # found in the LICENSE file. | ||
|
|
||
| # Stop on first error | ||
| set -e | ||
|
|
||
| # Get the directory of this script, then go up to camera_android_camerax root | ||
| SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )" | ||
| CAMERAX_DIR="$SCRIPT_DIR/../../../.." | ||
|
|
||
| echo "🔍 Checking if environment is ready for new work..." | ||
|
|
||
| # 1. Check symlinks resolve | ||
| echo "1️⃣ Checking skill symlinks..." | ||
| broken_links=$(find "$CAMERAX_DIR/.agents/skills" -type l ! -exec test -e {} \; -print) | ||
| if [ -n "$broken_links" ]; then | ||
| echo "❌ Error: Found broken symlinks in .agents/skills:" | ||
| echo "$broken_links" | ||
| exit 1 | ||
| fi | ||
| echo "✅ All symlinks resolve correctly." | ||
|
|
||
| # 2. Check git state | ||
| echo "2️⃣ Checking git state..." | ||
| # Check the whole repository git state | ||
| if [ -n "$(git status --porcelain)" ]; then | ||
| echo "❌ Error: Git working directory is not clean. Please commit or stash your changes before starting new work." | ||
| exit 1 | ||
| fi | ||
|
reidbaker marked this conversation as resolved.
|
||
| echo "✅ Git working directory is clean." | ||
|
|
||
| # 3. Check dart and flutter | ||
| echo "3️⃣ Checking Flutter and Dart..." | ||
| if ! command -v flutter &> /dev/null; then | ||
| echo "❌ Error: 'flutter' is not on the PATH." | ||
| exit 1 | ||
| fi | ||
| if ! command -v dart &> /dev/null; then | ||
| echo "❌ Error: 'dart' is not on the PATH." | ||
| exit 1 | ||
| fi | ||
| echo "✅ Flutter and Dart are on the PATH." | ||
|
|
||
| # 4. Check dependencies in camera_android_camerax | ||
| echo "4️⃣ Checking dependencies in camera_android_camerax..." | ||
| cd "$CAMERAX_DIR" | ||
| if ! flutter pub get; then | ||
| echo "❌ Error: Failed to resolve dependencies." | ||
| exit 1 | ||
| fi | ||
| echo "✅ Dependencies are resolved and ready." | ||
|
|
||
| echo "🎉 Environment is fully ready!" | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| ../../../../../third_party/dart-lang-skills/.agents/skills/dart-add-unit-test |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| ../../../../../third_party/dart-lang-skills/.agents/skills/dart-collect-coverage |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| ../../../../../third_party/dart-lang-skills/.agents/skills/dart-generate-test-mocks |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| ../../../../../third_party/dart-lang-skills/.agents/skills/dart-run-static-analysis |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| ../../../../../third_party/flutter-skills/.agents/skills/flutter-add-integration-test |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| ../../../../../third_party/mattpocock-skills/.agents/skills/grill-me |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| ../../../../../third_party/obra-superpowers/.agents/skills/receiving-code-review |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| .agents/ |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| dart_skills_lint: | ||
| rules: | ||
| check-relative-paths: error | ||
| check-trailing-whitespace: error | ||
| directories: | ||
| - path: "skills" | ||
| individual_skills: | ||
| - path: ".agents/skills/check-readiness" | ||
| rules: | ||
| prevent-skills-sh-publishing: error |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| # Published Skills | ||
|
|
||
| This directory contains AI agent skills that are intended to be published to pub.dev. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,76 @@ | ||
| // Copyright 2013 The Flutter Authors | ||
| // Use of this source code is governed by a BSD-style license that can be | ||
| // found in the LICENSE file. | ||
|
|
||
| import 'dart:io'; | ||
|
|
||
| import 'package:dart_skills_lint/dart_skills_lint.dart'; | ||
|
|
||
| /// A custom lint rule that enforces that all skills tracked in version control | ||
| /// are marked as internal. | ||
| /// | ||
| /// This rule is specifically used to prevent the accidental publishing of | ||
| /// workspace-specific agent skills to the global public skills registry. It | ||
| /// uses `git ls-files` to determine if a skill directory is checked into git, | ||
| /// and if it is, strictly requires that the `metadata: internal: true` | ||
| /// frontmatter is present in the `SKILL.md` file. | ||
| class EnforceTrackedSkillsInternalRule extends SkillRule { | ||
| @override | ||
| String get name => 'enforce-tracked-skills-internal'; | ||
|
|
||
| @override | ||
| AnalysisSeverity get severity => AnalysisSeverity.error; | ||
|
|
||
| @override | ||
| Future<List<ValidationError>> validate(SkillContext context) async { | ||
| // Check if any files in the skill directory are tracked in git | ||
| final ProcessResult processResult; | ||
| try { | ||
| processResult = await Process.run('git', ['ls-files', context.directory.path]); | ||
| } on ProcessException catch (e) { | ||
| return [ | ||
| ValidationError( | ||
| ruleId: name, | ||
| severity: severity, | ||
| file: 'SKILL.md', | ||
| message: | ||
| 'Failed to run git to check tracked status. Is git installed and on the PATH? Error: $e', | ||
| ), | ||
| ]; | ||
| } | ||
| if (processResult.exitCode != 0) { | ||
| return []; | ||
| } | ||
| final String output = (processResult.stdout as String).trim(); | ||
| if (output.isEmpty) { | ||
| // Not tracked by git, no enforcement needed | ||
| return []; | ||
| } | ||
|
|
||
| final Object? yaml = context.parsedYaml; | ||
| if (yaml is! Map) { | ||
| return [ | ||
| ValidationError( | ||
| ruleId: name, | ||
| severity: severity, | ||
| file: 'SKILL.md', | ||
| message: 'Tracked skills must have "metadata: internal: true" in SKILL.md frontmatter.', | ||
| ), | ||
| ]; | ||
| } | ||
|
|
||
| final Object? metadata = yaml['metadata']; | ||
| if (metadata is! Map || metadata['internal'] != true) { | ||
| return [ | ||
| ValidationError( | ||
| ruleId: name, | ||
| severity: severity, | ||
| file: 'SKILL.md', | ||
| message: 'Tracked skills must have "metadata: internal: true" in SKILL.md frontmatter.', | ||
| ), | ||
| ]; | ||
| } | ||
|
|
||
| return []; | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| // Copyright 2013 The Flutter Authors | ||
| // Use of this source code is governed by a BSD-style license that can be | ||
| // found in the LICENSE file. | ||
|
|
||
| import 'dart:async'; | ||
|
|
||
| import 'package:dart_skills_lint/dart_skills_lint.dart'; | ||
| import 'package:flutter/foundation.dart'; | ||
| import 'package:flutter_test/flutter_test.dart'; | ||
| import 'package:logging/logging.dart'; | ||
|
|
||
| import 'enforce_tracked_skills_internal_rule.dart'; | ||
|
|
||
| void main() { | ||
| test('Validate Skills', () async { | ||
| final Level oldLevel = Logger.root.level; | ||
| Logger.root.level = Level.ALL; | ||
| final StreamSubscription<LogRecord> subscription = Logger.root.onRecord.listen((record) { | ||
| debugPrint(record.message); | ||
| }); | ||
|
|
||
| try { | ||
| final Configuration config = await ConfigParser.loadConfig(); | ||
| final bool isValid = await validateSkills( | ||
| config: config, | ||
| customRules: [EnforceTrackedSkillsInternalRule()], | ||
| ); | ||
| expect(isValid, isTrue, reason: 'Skills validation failed. See above for details.'); | ||
| } finally { | ||
| Logger.root.level = oldLevel; | ||
| await subscription.cancel(); | ||
| } | ||
| }); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -190,20 +190,105 @@ class PublishCheckCommand extends PackageLoopingCommand { | |
| return true; | ||
| } | ||
|
|
||
| if (!getBoolArg(_allowPrereleaseFlag)) { | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this code was not deleted only moved. |
||
| return false; | ||
| } | ||
|
|
||
| await stdOutCompleter.future; | ||
| await stdInCompleter.future; | ||
|
|
||
| final output = outputBuffer.toString(); | ||
|
|
||
| // TODO(reidbaker): Remove this custom error handling for gitignored files | ||
| // once https://github.com/dart-lang/pub/issues/4841 is resolved. | ||
| if (await process.exitCode == 65 && _onlyPubignoreWarnings(output, package)) { | ||
| print('Ignoring warning about gitignored files because they are in .pubignore.'); | ||
| return true; | ||
| } | ||
|
|
||
| if (!getBoolArg(_allowPrereleaseFlag)) { | ||
| return false; | ||
| } | ||
|
|
||
| return output.contains('Package has 1 warning') && | ||
| output.contains( | ||
| 'Packages with an SDK constraint on a pre-release of the Dart SDK should themselves be published as a pre-release version.', | ||
| ); | ||
| } | ||
|
|
||
| bool _onlyPubignoreWarnings(String output, RepositoryPackage package) { | ||
| if (!output.contains('Files that are checked in while gitignored:')) { | ||
| return false; | ||
| } | ||
|
|
||
| final warningCountRegex = RegExp(r'Package has (\d+) warning'); | ||
| final Match? match = warningCountRegex.firstMatch(output); | ||
| if (match != null) { | ||
| final int count = int.parse(match.group(1)!); | ||
| if (count > 1) { | ||
| return false; | ||
| } | ||
| } | ||
|
|
||
| final List<String> lines = output.split('\n'); | ||
| var inFilesSection = false; | ||
| final gitignoredFiles = <String>[]; | ||
|
|
||
| for (final line in lines) { | ||
| if (line.trim() == 'Files that are checked in while gitignored:') { | ||
| inFilesSection = true; | ||
| continue; | ||
| } | ||
| if (inFilesSection) { | ||
| if (line.trim().isEmpty) { | ||
| continue; | ||
| } | ||
| if (line.startsWith(' ') && !line.startsWith(' ')) { | ||
| gitignoredFiles.add(line.trim()); | ||
| } else if (!line.startsWith(' ')) { | ||
| inFilesSection = false; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| if (gitignoredFiles.isEmpty) { | ||
| return false; | ||
| } | ||
|
|
||
| final io.File pubignoreFile = package.directory.childFile('.pubignore'); | ||
| if (!pubignoreFile.existsSync()) { | ||
| return false; | ||
| } | ||
|
|
||
| final List<String> pubignoreLines = pubignoreFile | ||
| .readAsLinesSync() | ||
| .map((String line) => line.trim()) | ||
| .where((String line) => line.isNotEmpty && !line.startsWith('#')) | ||
| .toList(); | ||
|
|
||
| for (final file in gitignoredFiles) { | ||
| var isIgnored = false; | ||
| for (final ignoreRule in pubignoreLines) { | ||
| var rule = ignoreRule; | ||
| if (rule.startsWith('/')) { | ||
| rule = rule.substring(1); | ||
| } | ||
| if (rule.endsWith('/')) { | ||
| if (file.startsWith(rule)) { | ||
| isIgnored = true; | ||
| break; | ||
| } | ||
| } else { | ||
| if (file == rule || file.startsWith('$rule/')) { | ||
| isIgnored = true; | ||
| break; | ||
| } | ||
| } | ||
| } | ||
| if (!isIgnored) { | ||
| return false; | ||
| } | ||
| } | ||
|
|
||
| return true; | ||
| } | ||
|
|
||
| /// Returns true if the package has been explicitly marked as not for | ||
| /// publishing. | ||
| bool _isMarkedAsUnpublishable(RepositoryPackage package) { | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.