gravity-cli 0.10.0__tar.gz → 0.11.0__tar.gz
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.
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/AGENT_STANDARD.md +1 -1
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/AGENT_STANDARD_V2.md +1 -1
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/PKG-INFO +4 -4
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/README.md +2 -2
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/gravity_schema/catalog.yaml +45 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/gravity_schema/contract.py +2 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/gravity_schema/manifest.py +15 -3
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/gravity_schema/manifest_v2.py +2 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/gravity_schema/rules.py +25 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/gravity_schema/rules_cases.json +19 -2
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/gravity_schema/specs.py +52 -8
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/pyproject.toml +1 -1
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/schema/manifest.schema.json +76 -3
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/tests/test_manifest.py +8 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/tests/test_rules.py +39 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/pyproject.toml +2 -2
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/src/gravity_cli/BUILDER_GUIDE.md +2 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/src/gravity_cli/BUILDER_GUIDE_V2.md +1 -1
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/src/gravity_cli/CHANGELOG.md +13 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/src/gravity_cli/_runner_script.py +26 -1
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/src/gravity_cli/commands/run.py +2 -1
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/src/gravity_cli/dev_page/index.html +9 -3
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/src/gravity_cli/docs/Gravity.agent.md +49 -9
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/src/gravity_cli/inputs.py +13 -2
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/src/gravity_cli/timeline.py +17 -1
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/tests/test_inputs_memory.py +18 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/tests/test_templates.py +27 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/tests/test_timeline.py +17 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/uv.lock +2 -2
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/.env.example +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/.github/workflows/ci.yml +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/.github/workflows/composio-watch.yml +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/.github/workflows/release.yml +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/.gitignore +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/LICENSE +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/NOTICE +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/RELEASING.md +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/TEMPLATES.md +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/LICENSE +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/NOTICE +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/README.md +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/gravity_schema/__init__.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/gravity_schema/__main__.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/gravity_schema/built_ins.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/gravity_schema/catalog.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/gravity_schema/catalog_imported.yaml +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/gravity_schema/cron.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/gravity_schema/describe.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/gravity_schema/errors.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/gravity_schema/export.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/gravity_schema/gen_catalog.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/gravity_schema/gen_vocabulary.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/gravity_schema/instance.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/gravity_schema/source_scan.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/gravity_schema/validation.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/gravity_schema/vocabulary/__init__.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/gravity_schema/vocabulary/__main__.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/gravity_schema/vocabulary/capabilities.yaml +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/gravity_schema/vocabulary/connectors/airtable.yaml +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/gravity_schema/vocabulary/connectors/asana.yaml +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/gravity_schema/vocabulary/connectors/browser_tool.yaml +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/gravity_schema/vocabulary/connectors/composio_search.yaml +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/gravity_schema/vocabulary/connectors/dropbox.yaml +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/gravity_schema/vocabulary/connectors/exa.yaml +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/gravity_schema/vocabulary/connectors/excel.yaml +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/gravity_schema/vocabulary/connectors/firecrawl.yaml +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/gravity_schema/vocabulary/connectors/github.yaml +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/gravity_schema/vocabulary/connectors/gmail.yaml +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/gravity_schema/vocabulary/connectors/googlecalendar.yaml +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/gravity_schema/vocabulary/connectors/googledocs.yaml +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/gravity_schema/vocabulary/connectors/googledrive.yaml +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/gravity_schema/vocabulary/connectors/googlesheets.yaml +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/gravity_schema/vocabulary/connectors/googleslides.yaml +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/gravity_schema/vocabulary/connectors/googletasks.yaml +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/gravity_schema/vocabulary/connectors/hackernews.yaml +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/gravity_schema/vocabulary/connectors/hubspot.yaml +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/gravity_schema/vocabulary/connectors/instagram.yaml +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/gravity_schema/vocabulary/connectors/jira.yaml +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/gravity_schema/vocabulary/connectors/linear.yaml +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/gravity_schema/vocabulary/connectors/linkedin.yaml +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/gravity_schema/vocabulary/connectors/microsoft_teams.yaml +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/gravity_schema/vocabulary/connectors/notion.yaml +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/gravity_schema/vocabulary/connectors/outlook.yaml +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/gravity_schema/vocabulary/connectors/perplexityai.yaml +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/gravity_schema/vocabulary/connectors/pinterest.yaml +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/gravity_schema/vocabulary/connectors/reddit.yaml +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/gravity_schema/vocabulary/connectors/slack.yaml +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/gravity_schema/vocabulary/connectors/tavily.yaml +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/gravity_schema/vocabulary/connectors/youtube.yaml +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/gravity_schema/vocabulary/core_shapes.yaml +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/gravity_schema/vocabulary/generated_shapes.yaml +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/gravity_schema/vocabulary/policy.yaml +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/gravity_schema/vocabulary/schemas/airtable.json +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/gravity_schema/vocabulary/schemas/asana.json +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/gravity_schema/vocabulary/schemas/browser_tool.json +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/gravity_schema/vocabulary/schemas/composio_search.json +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/gravity_schema/vocabulary/schemas/dropbox.json +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/gravity_schema/vocabulary/schemas/exa.json +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/gravity_schema/vocabulary/schemas/excel.json +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/gravity_schema/vocabulary/schemas/firecrawl.json +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/gravity_schema/vocabulary/schemas/github.json +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/gravity_schema/vocabulary/schemas/gmail.json +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/gravity_schema/vocabulary/schemas/googlecalendar.json +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/gravity_schema/vocabulary/schemas/googledocs.json +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/gravity_schema/vocabulary/schemas/googledrive.json +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/gravity_schema/vocabulary/schemas/googlesheets.json +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/gravity_schema/vocabulary/schemas/googleslides.json +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/gravity_schema/vocabulary/schemas/googletasks.json +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/gravity_schema/vocabulary/schemas/hackernews.json +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/gravity_schema/vocabulary/schemas/hubspot.json +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/gravity_schema/vocabulary/schemas/instagram.json +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/gravity_schema/vocabulary/schemas/jira.json +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/gravity_schema/vocabulary/schemas/linear.json +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/gravity_schema/vocabulary/schemas/linkedin.json +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/gravity_schema/vocabulary/schemas/microsoft_teams.json +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/gravity_schema/vocabulary/schemas/notion.json +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/gravity_schema/vocabulary/schemas/outlook.json +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/gravity_schema/vocabulary/schemas/perplexityai.json +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/gravity_schema/vocabulary/schemas/pinterest.json +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/gravity_schema/vocabulary/schemas/reddit.json +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/gravity_schema/vocabulary/schemas/slack.json +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/gravity_schema/vocabulary/schemas/tavily.json +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/gravity_schema/vocabulary/schemas/youtube.json +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/gravity_schema/vocabulary/schemas.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/gravity_schema/vocabulary/shapes.d/ochat.yaml +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/gravity_schema/vocabulary/shapes.d/ocrm.yaml +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/gravity_schema/vocabulary/shapes.d/ogh.yaml +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/gravity_schema/vocabulary/shapes.d/oms.yaml +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/gravity_schema/vocabulary/shapes.d/oweb.yaml +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/gravity_schema/vocabulary/shapes.d/owork.yaml +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/gravity_schema/vocabulary/shapes.d/shared.yaml +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/gravity_schema/vocabulary/sync.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/gravity_schema/vocabulary/verbs.d/ochat.yaml +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/gravity_schema/vocabulary/verbs.d/ocrm.yaml +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/gravity_schema/vocabulary/verbs.d/ogh.yaml +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/gravity_schema/vocabulary/verbs.d/oms.yaml +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/gravity_schema/vocabulary/verbs.d/oweb.yaml +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/gravity_schema/vocabulary/verbs.d/owork.yaml +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/gravity_schema/vocabulary/verbs.d/rchat.yaml +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/gravity_schema/vocabulary/verbs.d/rfiles.yaml +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/gravity_schema/vocabulary/verbs.d/rgh.yaml +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/gravity_schema/vocabulary/verbs.d/rtrack.yaml +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/gravity_schema/vocabulary/verbs.d/rwork.yaml +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/gravity_schema/vocabulary/verbs.yaml +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/tests/conftest.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/tests/fixtures/demo_manifests.yaml +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/tests/test_accounts.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/tests/test_actions_memory.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/tests/test_catalog_parity.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/tests/test_cron.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/tests/test_describe.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/tests/test_errors.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/tests/test_generated_tables.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/tests/test_instance.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/tests/test_json_schema.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/tests/test_kind_outputs.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/tests/test_manifest_v2.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/tests/test_place_maker.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/tests/test_slots.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/tests/test_source_scan.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/tests/test_sync.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/tests/test_validation.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/tests/test_vocabulary.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/scripts/composio-watch.sh +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/src/gravity_cli/__init__.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/src/gravity_cli/__main__.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/src/gravity_cli/api.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/src/gravity_cli/changelog.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/src/gravity_cli/cli.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/src/gravity_cli/commands/__init__.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/src/gravity_cli/commands/adapt.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/src/gravity_cli/commands/build.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/src/gravity_cli/commands/capabilities.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/src/gravity_cli/commands/changelog.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/src/gravity_cli/commands/check.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/src/gravity_cli/commands/connect.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/src/gravity_cli/commands/dev.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/src/gravity_cli/commands/docs.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/src/gravity_cli/commands/guide.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/src/gravity_cli/commands/help.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/src/gravity_cli/commands/init.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/src/gravity_cli/commands/login.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/src/gravity_cli/commands/memory.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/src/gravity_cli/commands/push.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/src/gravity_cli/commands/runs.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/src/gravity_cli/commands/schedule.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/src/gravity_cli/commands/tools.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/src/gravity_cli/commands/update.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/src/gravity_cli/commands/validate.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/src/gravity_cli/config.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/src/gravity_cli/dev.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/src/gravity_cli/docs/Gravity.getting-started.md +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/src/gravity_cli/docs/problem-to-agent.md +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/src/gravity_cli/localrun.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/src/gravity_cli/manifest.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/src/gravity_cli/project.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/src/gravity_cli/templates/chat/.gitignore +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/src/gravity_cli/templates/chat/manifest.yaml +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/src/gravity_cli/templates/chat/requirements.txt +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/src/gravity_cli/templates/chat/src/agent.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/src/gravity_cli/templates/deepagent/.gitignore +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/src/gravity_cli/templates/deepagent/manifest.yaml +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/src/gravity_cli/templates/deepagent/requirements.txt +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/src/gravity_cli/templates/deepagent/src/agent.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/src/gravity_cli/templates/minimal/.gitignore +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/src/gravity_cli/templates/minimal/manifest.yaml +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/src/gravity_cli/templates/minimal/requirements.txt +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/src/gravity_cli/templates/minimal/src/agent.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/src/gravity_cli/templates/structured/.gitignore +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/src/gravity_cli/templates/structured/manifest.yaml +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/src/gravity_cli/templates/structured/requirements.txt +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/src/gravity_cli/templates/structured/src/agent.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/src/gravity_cli/templates/structured/src/gateway.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/src/gravity_cli/templates/structured/src/nodes/agent.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/src/gravity_cli/templates/structured/src/prompts.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/src/gravity_cli/templates/structured/src/state.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/src/gravity_cli/templates/v2/chat/.gitignore +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/src/gravity_cli/templates/v2/chat/manifest.yaml +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/src/gravity_cli/templates/v2/chat/requirements.txt +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/src/gravity_cli/templates/v2/chat/src/agent.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/src/gravity_cli/templates/v2/chat/tests/test_agent.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/src/gravity_cli/templates/v2/deepagent/.gitignore +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/src/gravity_cli/templates/v2/deepagent/manifest.yaml +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/src/gravity_cli/templates/v2/deepagent/requirements.txt +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/src/gravity_cli/templates/v2/deepagent/src/agent.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/src/gravity_cli/templates/v2/deepagent/tests/test_agent.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/src/gravity_cli/templates/v2/minimal/.gitignore +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/src/gravity_cli/templates/v2/minimal/manifest.yaml +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/src/gravity_cli/templates/v2/minimal/requirements.txt +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/src/gravity_cli/templates/v2/minimal/src/agent.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/src/gravity_cli/templates/v2/minimal/tests/test_agent.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/src/gravity_cli/templates/v2/structured/.gitignore +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/src/gravity_cli/templates/v2/structured/manifest.yaml +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/src/gravity_cli/templates/v2/structured/requirements.txt +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/src/gravity_cli/templates/v2/structured/src/__init__.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/src/gravity_cli/templates/v2/structured/src/agent.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/src/gravity_cli/templates/v2/structured/src/gateway.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/src/gravity_cli/templates/v2/structured/src/nodes/__init__.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/src/gravity_cli/templates/v2/structured/src/nodes/agent.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/src/gravity_cli/templates/v2/structured/src/prompts.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/src/gravity_cli/templates/v2/structured/src/state.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/src/gravity_cli/templates/v2/structured/tests/test_agent.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/src/gravity_cli/ui.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/src/gravity_cli/updater.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/src/gravity_cli/workspace.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/starter/manifest.yaml +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/starter/requirements.txt +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/starter/src/agent.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/starter/src/summary.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/starter/tests/test_summary.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/starter-v2/manifest.yaml +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/starter-v2/requirements.txt +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/starter-v2/src/agent.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/starter-v2/src/summary.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/starter-v2/tests/test_summary.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/tests/conftest.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/tests/test_adapt.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/tests/test_agent_guide.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/tests/test_agents.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/tests/test_api.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/tests/test_build_push.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/tests/test_changelog.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/tests/test_check.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/tests/test_connect.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/tests/test_connect_v2.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/tests/test_dev.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/tests/test_dev_v2.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/tests/test_gateway_token.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/tests/test_localrun.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/tests/test_manifest_integration.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/tests/test_run.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/tests/test_run_v2.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/tests/test_runs.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/tests/test_schedule.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/tests/test_schedule_v2.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/tests/test_session.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/tests/test_templates_v2.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/tests/test_tools.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/tests/test_ui.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/tests/test_updater.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/tests/test_v2_cli.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/tests/test_validate.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/tests/test_validate_v2.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/tests/test_welcome.py +0 -0
- {gravity_cli-0.10.0 → gravity_cli-0.11.0}/tests/test_workspace.py +0 -0
|
@@ -348,7 +348,7 @@ to one address, with the output's content in the message body and no
|
|
|
348
348
|
attachment; a thread sends at most 200 a day. The platform sends it, not the
|
|
349
349
|
agent, so the agent needs no Gmail tool and no approval for it.
|
|
350
350
|
|
|
351
|
-
Renderers: `markdown`, `docx`, `pptx`, `rows` (the first table, as CSV). Each
|
|
351
|
+
Renderers: `markdown`, `docx`, `pptx`, `pdf`, `rows` (the first table, as CSV), `xlsx` (every table, a sheet each). Each
|
|
352
352
|
consumer picks outputs and destinations per run. The agent writes one
|
|
353
353
|
**corpus** into its final state, and every output is rendered from it:
|
|
354
354
|
|
|
@@ -384,7 +384,7 @@ record tagged with its app in `extra.app`. The platform delivers it after the
|
|
|
384
384
|
run, not the agent, so the agent declares no write for it; an email goes at
|
|
385
385
|
most once per run and a thread sends at most 200 a day, extra places included.
|
|
386
386
|
|
|
387
|
-
Renderers: `markdown`, `docx`, `pptx`, `rows` (the first table, as CSV). Each
|
|
387
|
+
Renderers: `markdown`, `docx`, `pptx`, `pdf`, `rows` (the first table, as CSV), `xlsx` (every table, a sheet each). Each
|
|
388
388
|
consumer picks outputs and destinations per run. The agent writes one
|
|
389
389
|
**corpus** into its final state, and every output is rendered from it:
|
|
390
390
|
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: gravity-cli
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.11.0
|
|
4
4
|
Summary: gravity cli — init, run, and push python agents to the Gravity marketplace
|
|
5
5
|
License-Expression: Apache-2.0
|
|
6
6
|
License-File: LICENSE
|
|
7
7
|
License-File: NOTICE
|
|
8
8
|
Requires-Python: >=3.12
|
|
9
|
-
Requires-Dist: gravity-schema==0.
|
|
9
|
+
Requires-Dist: gravity-schema==0.11.0
|
|
10
10
|
Requires-Dist: httpx>=0.27.0
|
|
11
11
|
Requires-Dist: keyring>=25.0.0
|
|
12
12
|
Requires-Dist: python-dotenv>=1.0.0
|
|
@@ -720,7 +720,7 @@ slots: # a part the consumer chooses; each adapter ge
|
|
|
720
720
|
|
|
721
721
|
outputs: # extra formats the platform renders and delivers itself
|
|
722
722
|
report:
|
|
723
|
-
renderer: markdown # markdown | docx | pptx | rows
|
|
723
|
+
renderer: markdown # markdown | docx | pptx | pdf | rows | xlsx
|
|
724
724
|
label: "Digest as a document"
|
|
725
725
|
destinations: [download]
|
|
726
726
|
```
|
|
@@ -752,7 +752,7 @@ outputs: # extra formats the platform renders and deliv
|
|
|
752
752
|
| `triggers.webhook` | no | none | A list of events; `github.push` is the only one today. |
|
|
753
753
|
| `state.max_kb` | no | no memory | Include `state:` to keep memory between runs, in `state["memory"]`. 1 to 256 KB. |
|
|
754
754
|
| `slots.<name>` | no | none | A swappable part: `label`, `default` adapter, and `adapters` mapping each adapter name to the tools it may call. Code lives in `src/adapters/<slot>/<adapter>.py`. Slot names cannot repeat an input's name. |
|
|
755
|
-
| `outputs.<name>` | no | none | Up to 8 extra formats rendered from the result: `renderer` (`markdown`, `docx`, `pptx` or `
|
|
755
|
+
| `outputs.<name>` | no | none | Up to 8 extra formats rendered from the result: `renderer` (`markdown`, `docx`, `pptx`, `pdf`, `rows` or `xlsx`), `label` and `destinations` (`download`, or a catalog tool such as `gmail.send`). |
|
|
756
756
|
|
|
757
757
|
Unknown fields are rejected rather than ignored, so a typo is reported instead of silently dropped.
|
|
758
758
|
|
|
@@ -703,7 +703,7 @@ slots: # a part the consumer chooses; each adapter ge
|
|
|
703
703
|
|
|
704
704
|
outputs: # extra formats the platform renders and delivers itself
|
|
705
705
|
report:
|
|
706
|
-
renderer: markdown # markdown | docx | pptx | rows
|
|
706
|
+
renderer: markdown # markdown | docx | pptx | pdf | rows | xlsx
|
|
707
707
|
label: "Digest as a document"
|
|
708
708
|
destinations: [download]
|
|
709
709
|
```
|
|
@@ -735,7 +735,7 @@ outputs: # extra formats the platform renders and deliv
|
|
|
735
735
|
| `triggers.webhook` | no | none | A list of events; `github.push` is the only one today. |
|
|
736
736
|
| `state.max_kb` | no | no memory | Include `state:` to keep memory between runs, in `state["memory"]`. 1 to 256 KB. |
|
|
737
737
|
| `slots.<name>` | no | none | A swappable part: `label`, `default` adapter, and `adapters` mapping each adapter name to the tools it may call. Code lives in `src/adapters/<slot>/<adapter>.py`. Slot names cannot repeat an input's name. |
|
|
738
|
-
| `outputs.<name>` | no | none | Up to 8 extra formats rendered from the result: `renderer` (`markdown`, `docx`, `pptx` or `
|
|
738
|
+
| `outputs.<name>` | no | none | Up to 8 extra formats rendered from the result: `renderer` (`markdown`, `docx`, `pptx`, `pdf`, `rows` or `xlsx`), `label` and `destinations` (`download`, or a catalog tool such as `gmail.send`). |
|
|
739
739
|
|
|
740
740
|
Unknown fields are rejected rather than ignored, so a typo is reported instead of silently dropped.
|
|
741
741
|
|
{gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/gravity_schema/catalog.yaml
RENAMED
|
@@ -74,6 +74,15 @@
|
|
|
74
74
|
guarantee: certified
|
|
75
75
|
side_effect: read
|
|
76
76
|
|
|
77
|
+
- name: treg.email_find
|
|
78
|
+
slug: null
|
|
79
|
+
toolkit: null
|
|
80
|
+
description: find and verify a person's work email from their LinkedIn URL, or a full name plus the company's email domain; served by the gateway through the team's lookup account (a fraction of a cent a call), capped per call and verified in the same call
|
|
81
|
+
scopes: []
|
|
82
|
+
breadth: generic
|
|
83
|
+
guarantee: certified
|
|
84
|
+
side_effect: read
|
|
85
|
+
|
|
77
86
|
- name: browser.act
|
|
78
87
|
slug: null
|
|
79
88
|
toolkit: null
|
|
@@ -155,6 +164,42 @@
|
|
|
155
164
|
guarantee: certified
|
|
156
165
|
side_effect: write
|
|
157
166
|
|
|
167
|
+
- name: sheets.create
|
|
168
|
+
slug: GOOGLESHEETS_CREATE_GOOGLE_SHEET1
|
|
169
|
+
toolkit: googlesheets
|
|
170
|
+
description: create a new Google Sheet in the connected Google account
|
|
171
|
+
scopes: [sheets]
|
|
172
|
+
breadth: generic
|
|
173
|
+
guarantee: certified
|
|
174
|
+
side_effect: write
|
|
175
|
+
|
|
176
|
+
- name: sheets.add_tab
|
|
177
|
+
slug: GOOGLESHEETS_ADD_SHEET
|
|
178
|
+
toolkit: googlesheets
|
|
179
|
+
description: add a tab to a Google Sheet in the connected Google account
|
|
180
|
+
scopes: [sheets]
|
|
181
|
+
breadth: generic
|
|
182
|
+
guarantee: certified
|
|
183
|
+
side_effect: write
|
|
184
|
+
|
|
185
|
+
- name: docs.read
|
|
186
|
+
slug: GOOGLEDOCS_GET_DOCUMENT_PLAINTEXT
|
|
187
|
+
toolkit: googledocs
|
|
188
|
+
description: read a Google Doc in the connected Google account as plain text (document_id, from a google-doc input)
|
|
189
|
+
scopes: [docs]
|
|
190
|
+
breadth: generic
|
|
191
|
+
guarantee: certified
|
|
192
|
+
side_effect: read
|
|
193
|
+
|
|
194
|
+
- name: docs.create
|
|
195
|
+
slug: GOOGLEDOCS_CREATE_DOCUMENT_MARKDOWN
|
|
196
|
+
toolkit: googledocs
|
|
197
|
+
description: create a Google Doc from markdown in the connected Google account
|
|
198
|
+
scopes: [docs]
|
|
199
|
+
breadth: generic
|
|
200
|
+
guarantee: certified
|
|
201
|
+
side_effect: write
|
|
202
|
+
|
|
158
203
|
- name: slack.send
|
|
159
204
|
slug: SLACK_SEND_MESSAGE
|
|
160
205
|
toolkit: slack
|
{gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/gravity_schema/contract.py
RENAMED
|
@@ -106,6 +106,8 @@ MAX_INPUTS: Final[int] = 50
|
|
|
106
106
|
MAX_TOOLS: Final[int] = 50
|
|
107
107
|
MAX_OPTIONS: Final[int] = 100
|
|
108
108
|
MAX_FILE_EXTENSIONS: Final[int] = 20
|
|
109
|
+
# A file input with `max` (several files): the most it may ask for. Each upload is up to 25 MB.
|
|
110
|
+
MAX_FILES: Final[int] = 20
|
|
109
111
|
MAX_NAME_LENGTH: Final[int] = 64
|
|
110
112
|
MAX_ENTRYPOINT_LENGTH: Final[int] = 256
|
|
111
113
|
MAX_LABEL_LENGTH: Final[int] = 200
|
{gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/gravity_schema/manifest.py
RENAMED
|
@@ -319,11 +319,23 @@ class Manifest(BaseModel):
|
|
|
319
319
|
|
|
320
320
|
@model_validator(mode="after")
|
|
321
321
|
def _check_monitor_has_a_trigger(self) -> Manifest:
|
|
322
|
-
if self.kind is AgentKind.MONITOR and self.triggers.schedule is None and not self.triggers.webhook
|
|
322
|
+
if (self.kind is AgentKind.MONITOR and self.triggers.schedule is None and not self.triggers.webhook
|
|
323
|
+
and self.triggers.email is None):
|
|
323
324
|
raise PydanticCustomError(
|
|
324
325
|
ErrorCode.INVALID_KIND.value,
|
|
325
|
-
"A monitor needs a schedule or a webhook trigger.",
|
|
326
|
-
{"remediation": "Add triggers.schedule or triggers.webhook, or use kind: interactive."},
|
|
326
|
+
"A monitor needs a schedule, an email or a webhook trigger.",
|
|
327
|
+
{"remediation": "Add triggers.schedule, triggers.email or triggers.webhook, or use kind: interactive."},
|
|
328
|
+
)
|
|
329
|
+
return self
|
|
330
|
+
|
|
331
|
+
@model_validator(mode="after")
|
|
332
|
+
def _check_email_trigger_reads_gmail(self) -> Manifest:
|
|
333
|
+
# Gravity reads the new mail with the person's Gmail, under the agent's own permission.
|
|
334
|
+
if self.triggers.email is not None and "gmail.read" not in self.permissions.tools:
|
|
335
|
+
raise PydanticCustomError(
|
|
336
|
+
ErrorCode.INVALID_TRIGGER.value,
|
|
337
|
+
"triggers.email watches Gmail, but the agent does not declare gmail.read.",
|
|
338
|
+
{"remediation": "Add gmail.read to permissions.tools."},
|
|
327
339
|
)
|
|
328
340
|
return self
|
|
329
341
|
|
{gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/gravity_schema/manifest_v2.py
RENAMED
|
@@ -53,7 +53,9 @@ RENDERER_DESTINATIONS: dict[Renderer, tuple[str, ...]] = {
|
|
|
53
53
|
"post.create", "file.create"),
|
|
54
54
|
Renderer.DOCX: ("file.create", "document.create", "message.send"),
|
|
55
55
|
Renderer.PPTX: ("file.create", "presentation.create", "message.send"),
|
|
56
|
+
Renderer.PDF: ("file.create", "message.send"),
|
|
56
57
|
Renderer.ROWS: ("row.append", "file.create"),
|
|
58
|
+
Renderer.XLSX: ("file.create",),
|
|
57
59
|
}
|
|
58
60
|
|
|
59
61
|
# A filter on one of these fields takes one of the shape's listed values.
|
|
@@ -130,6 +130,21 @@ def _is_day(value: Any) -> bool:
|
|
|
130
130
|
return True
|
|
131
131
|
|
|
132
132
|
|
|
133
|
+
# The file id in a Google Doc or Sheet link, or a bare id (Google's are 25 or more of these characters).
|
|
134
|
+
_GOOGLE_PATH = {"google-doc": "document", "google-sheet": "spreadsheets"}
|
|
135
|
+
_GOOGLE_ID = re.compile(r"^[A-Za-z0-9_-]{25,}$")
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
def google_file_id(kind: str, value: Any) -> str | None:
|
|
139
|
+
"""'https://docs.google.com/spreadsheets/d/<id>/edit#gid=0' -> '<id>' for a google-sheet input (document for a
|
|
140
|
+
google-doc one); a bare id as it is; None for anything else, a Sheet's link in a Doc input included."""
|
|
141
|
+
text = value.strip() if isinstance(value, str) else ""
|
|
142
|
+
if _GOOGLE_ID.match(text):
|
|
143
|
+
return text
|
|
144
|
+
m = re.search(rf"docs\.google\.com/{_GOOGLE_PATH.get(kind, '-')}/d/([A-Za-z0-9_-]{{20,}})", text)
|
|
145
|
+
return m.group(1) if m else None
|
|
146
|
+
|
|
147
|
+
|
|
133
148
|
def _bounds(spec: InputSpec, value: Any) -> str | None:
|
|
134
149
|
label = spec.label or spec.name
|
|
135
150
|
if spec.many_days and not _blank(value):
|
|
@@ -140,6 +155,14 @@ def _bounds(spec: InputSpec, value: Any) -> str | None:
|
|
|
140
155
|
if spec.max is not None and len(value) > spec.max:
|
|
141
156
|
return f'"{label}": pick at most {spec.max} days.'
|
|
142
157
|
return None
|
|
158
|
+
if spec.many_files and not _blank(value):
|
|
159
|
+
if not isinstance(value, list) or not all(isinstance(v, str) and v.strip() for v in value):
|
|
160
|
+
return f'"{label}": upload the files again.'
|
|
161
|
+
if spec.min is not None and len(value) < spec.min:
|
|
162
|
+
return f'"{label}": upload at least {spec.min} files.'
|
|
163
|
+
if spec.max is not None and len(value) > spec.max:
|
|
164
|
+
return f'"{label}": upload at most {spec.max} files.'
|
|
165
|
+
return None
|
|
143
166
|
if spec.type is InputType.MULTI_SELECT and not _blank(value):
|
|
144
167
|
if not isinstance(value, list) or any(v not in (spec.options or []) for v in value):
|
|
145
168
|
return f'"{label}": pick from {", ".join(spec.options or [])}.'
|
|
@@ -166,6 +189,8 @@ def _check(inputs: list[InputSpec], shown: list[str], answers: dict[str, Any]) -
|
|
|
166
189
|
out.append((spec.name, f'"{spec.label or spec.name}": pick at least {spec.min}.'))
|
|
167
190
|
elif spec.many_days and spec.min and _blank(value):
|
|
168
191
|
out.append((spec.name, f'"{spec.label or spec.name}": pick at least {spec.min} days.'))
|
|
192
|
+
elif spec.many_files and spec.min and _blank(value):
|
|
193
|
+
out.append((spec.name, f'"{spec.label or spec.name}": upload at least {spec.min} files.'))
|
|
169
194
|
elif (problem := _bounds(spec, value)) is not None:
|
|
170
195
|
out.append((spec.name, problem))
|
|
171
196
|
return out
|
{gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/gravity_schema/rules_cases.json
RENAMED
|
@@ -12,7 +12,8 @@
|
|
|
12
12
|
{"name": "contact_source", "type": "static-dropdown", "label": "Contacts from", "options": ["gravity", "hunter", "both"], "default": "gravity"},
|
|
13
13
|
{"name": "hunter_key", "type": "secret", "label": "Your Hunter API key", "required": true, "show_if": {"contact_source": ["hunter", "both"]}},
|
|
14
14
|
{"name": "goal", "type": "action-choice", "label": "What do you want to do first?", "actions": ["find_companies", "write_emails"]},
|
|
15
|
-
{"name": "call_days", "type": "date", "label": "Days for a call", "min": 1, "max": 3, "show_if": {"goal": "write_emails"}}
|
|
15
|
+
{"name": "call_days", "type": "date", "label": "Days for a call", "min": 1, "max": 3, "show_if": {"goal": "write_emails"}},
|
|
16
|
+
{"name": "past_pitches", "type": "file", "label": "Past pitch decks", "accept": ["pdf"], "min": 1, "max": 2, "show_if": {"goal": "find_companies"}}
|
|
16
17
|
],
|
|
17
18
|
"slots": {
|
|
18
19
|
"deliver": {"label": "Deliver to", "default": "gravity", "adapters": {"gravity": [], "gmail": ["gmail.draft"]}},
|
|
@@ -79,6 +80,22 @@
|
|
|
79
80
|
{"name": "min days asks for at least one",
|
|
80
81
|
"answers": {"resume_text": "cv", "platforms": ["x"], "goal": "write_emails"},
|
|
81
82
|
"visible": ["resume_text", "platforms", "contact_source", "goal", "call_days"],
|
|
82
|
-
"problems": ["call_days"]}
|
|
83
|
+
"problems": ["call_days"]},
|
|
84
|
+
{"name": "a file with max takes a list of links",
|
|
85
|
+
"answers": {"resume_text": "cv", "platforms": ["x"], "goal": "find_companies", "past_pitches": ["https://x.test/uploads/a.pdf", "https://x.test/uploads/b.pdf"]},
|
|
86
|
+
"visible": ["resume_text", "platforms", "contact_source", "goal", "past_pitches"],
|
|
87
|
+
"problems": []},
|
|
88
|
+
{"name": "no more files than max",
|
|
89
|
+
"answers": {"resume_text": "cv", "platforms": ["x"], "goal": "find_companies", "past_pitches": ["https://x.test/a.pdf", "https://x.test/b.pdf", "https://x.test/c.pdf"]},
|
|
90
|
+
"visible": ["resume_text", "platforms", "contact_source", "goal", "past_pitches"],
|
|
91
|
+
"problems": ["past_pitches"]},
|
|
92
|
+
{"name": "several files are a list, not one link",
|
|
93
|
+
"answers": {"resume_text": "cv", "platforms": ["x"], "goal": "find_companies", "past_pitches": "https://x.test/a.pdf"},
|
|
94
|
+
"visible": ["resume_text", "platforms", "contact_source", "goal", "past_pitches"],
|
|
95
|
+
"problems": ["past_pitches"]},
|
|
96
|
+
{"name": "min files asks for at least one",
|
|
97
|
+
"answers": {"resume_text": "cv", "platforms": ["x"], "goal": "find_companies"},
|
|
98
|
+
"visible": ["resume_text", "platforms", "contact_source", "goal", "past_pitches"],
|
|
99
|
+
"problems": ["past_pitches"]}
|
|
83
100
|
]
|
|
84
101
|
}
|
|
@@ -35,12 +35,16 @@ class InputType(str, Enum):
|
|
|
35
35
|
# An API key or password. The platform seals it with KMS when it is submitted, keeps it
|
|
36
36
|
# out of every API response and log, and opens it only to hand it to the running agent.
|
|
37
37
|
SECRET = "secret"
|
|
38
|
-
# The agent gets a short-lived URL it fetches through the gateway.
|
|
38
|
+
# The agent gets a short-lived URL it fetches through the gateway; with `max`, a list of them (several files).
|
|
39
39
|
FILE = "file"
|
|
40
40
|
# Several of `options`; the value is a list.
|
|
41
41
|
MULTI_SELECT = "multi-select"
|
|
42
42
|
# One of this agent's declared `actions`; the chosen action runs (rules.py).
|
|
43
43
|
ACTION_CHOICE = "action-choice"
|
|
44
|
+
# A Google Doc or Sheet of the person's: they paste its link, the agent gets the file id (rules.google_file_id),
|
|
45
|
+
# which is what docs.read and sheets.read take.
|
|
46
|
+
GOOGLE_DOC = "google-doc"
|
|
47
|
+
GOOGLE_SHEET = "google-sheet"
|
|
44
48
|
|
|
45
49
|
|
|
46
50
|
# Which Python types each input's `default` may be.
|
|
@@ -57,6 +61,8 @@ _PYTHON_TYPES: dict[InputType, tuple[type, ...]] = {
|
|
|
57
61
|
InputType.FILE: (), # never has a default
|
|
58
62
|
InputType.MULTI_SELECT: (list,),
|
|
59
63
|
InputType.ACTION_CHOICE: (str,),
|
|
64
|
+
InputType.GOOGLE_DOC: (str,),
|
|
65
|
+
InputType.GOOGLE_SHEET: (str,),
|
|
60
66
|
}
|
|
61
67
|
|
|
62
68
|
# A `show_if` value: what the named input or slot must be for this question to be asked.
|
|
@@ -86,7 +92,9 @@ class Renderer(str, Enum):
|
|
|
86
92
|
MARKDOWN = "markdown"
|
|
87
93
|
DOCX = "docx"
|
|
88
94
|
PPTX = "pptx"
|
|
89
|
-
|
|
95
|
+
PDF = "pdf"
|
|
96
|
+
ROWS = "rows" # CSV of the first table
|
|
97
|
+
XLSX = "xlsx" # every table a sheet
|
|
90
98
|
|
|
91
99
|
|
|
92
100
|
class WebhookSource(str, Enum):
|
|
@@ -205,7 +213,7 @@ class InputSpec(BaseModel):
|
|
|
205
213
|
# Asked only when every named earlier input or slot has one of the given values (rules.py).
|
|
206
214
|
show_if: Annotated[ShowIf | None, Field(max_length=C.MAX_INPUTS)] = None
|
|
207
215
|
# multi-select: how many options may be picked. date: how many days; with `max` the answer is a list of
|
|
208
|
-
# "YYYY-MM-DD" days, picked on a calendar.
|
|
216
|
+
# "YYYY-MM-DD" days, picked on a calendar. file: how many files; with `max` the answer is a list of links.
|
|
209
217
|
min: Annotated[int | None, Field(ge=0, le=C.MAX_OPTIONS)] = None
|
|
210
218
|
max: Annotated[int | None, Field(ge=1, le=C.MAX_OPTIONS)] = None
|
|
211
219
|
# action-choice only: the declared actions offered, in order.
|
|
@@ -259,14 +267,27 @@ class InputSpec(BaseModel):
|
|
|
259
267
|
"""A date input that takes several days: its answer is a list of "YYYY-MM-DD"."""
|
|
260
268
|
return self.type is InputType.DATE and self.max is not None
|
|
261
269
|
|
|
270
|
+
@property
|
|
271
|
+
def many_files(self) -> bool:
|
|
272
|
+
"""A file input that takes several files: its answer is a list of links, one per file."""
|
|
273
|
+
return self.type is InputType.FILE and self.max is not None
|
|
274
|
+
|
|
262
275
|
@model_validator(mode="after")
|
|
263
276
|
def _check_choice_fields(self) -> InputSpec:
|
|
264
277
|
multi = self.type is InputType.MULTI_SELECT
|
|
265
|
-
if (self.min is not None or self.max is not None) and not (multi or self.type
|
|
278
|
+
if (self.min is not None or self.max is not None) and not (multi or self.type in (InputType.DATE, InputType.FILE)):
|
|
266
279
|
raise PydanticCustomError(
|
|
267
280
|
ErrorCode.INVALID_INPUT.value,
|
|
268
|
-
"Input '{value}' sets min or max but is not a multi-select or a
|
|
269
|
-
{"value": self.name, "remediation": "Set type to 'multi-select' or '
|
|
281
|
+
"Input '{value}' sets min or max but is not a multi-select, a date or a file.",
|
|
282
|
+
{"value": self.name, "remediation": "Set type to 'multi-select', 'date' or 'file', or remove min and max."},
|
|
283
|
+
)
|
|
284
|
+
file_bounds = self.type is InputType.FILE and (self.min is not None or self.max is not None)
|
|
285
|
+
if file_bounds and (self.max is None or (self.min or 0) > self.max or self.max > C.MAX_FILES):
|
|
286
|
+
raise PydanticCustomError(
|
|
287
|
+
ErrorCode.INVALID_INPUT.value,
|
|
288
|
+
"File input '{value}' asks for between {lo} and {hi} files.",
|
|
289
|
+
{"value": self.name, "lo": self.min or 0, "hi": self.max,
|
|
290
|
+
"remediation": f"Set `max` (how many files may be uploaded, at most {C.MAX_FILES}), and keep min <= max."},
|
|
270
291
|
)
|
|
271
292
|
days_bounds = self.type is InputType.DATE and (self.min is not None or self.max is not None)
|
|
272
293
|
if days_bounds and (self.max is None or (self.min or 0) > self.max):
|
|
@@ -465,6 +486,16 @@ class ScheduleSpec(BaseModel):
|
|
|
465
486
|
return v
|
|
466
487
|
|
|
467
488
|
|
|
489
|
+
class EmailTriggerSpec(BaseModel):
|
|
490
|
+
"""Run when new mail matching a Gmail search arrives in the person's inbox. Gravity checks every 5 minutes and
|
|
491
|
+
starts a run only when there is new mail, with the messages in inputs["event"]["emails"]."""
|
|
492
|
+
|
|
493
|
+
model_config = _STRICT
|
|
494
|
+
|
|
495
|
+
query: Annotated[str, Field(min_length=1, max_length=500)] # a Gmail search: "from:recruiting@acme.com is:unread"
|
|
496
|
+
consumer_can_change: bool = True
|
|
497
|
+
|
|
498
|
+
|
|
468
499
|
class TriggersSpec(BaseModel):
|
|
469
500
|
"""What starts a run. Declared so the consumer sees it before installing."""
|
|
470
501
|
|
|
@@ -473,14 +504,15 @@ class TriggersSpec(BaseModel):
|
|
|
473
504
|
manual: bool = True
|
|
474
505
|
schedule: ScheduleSpec | None = None
|
|
475
506
|
webhook: list[WebhookSource] = Field(default_factory=list)
|
|
507
|
+
email: EmailTriggerSpec | None = None
|
|
476
508
|
|
|
477
509
|
@model_validator(mode="after")
|
|
478
510
|
def _check_something_starts_it(self) -> TriggersSpec:
|
|
479
|
-
if not self.manual and self.schedule is None and not self.webhook:
|
|
511
|
+
if not self.manual and self.schedule is None and not self.webhook and self.email is None:
|
|
480
512
|
raise PydanticCustomError(
|
|
481
513
|
ErrorCode.INVALID_TRIGGER.value,
|
|
482
514
|
"Nothing can start this agent.",
|
|
483
|
-
{"remediation": "Set manual: true, or add a schedule or a webhook."},
|
|
515
|
+
{"remediation": "Set manual: true, or add a schedule, an email trigger or a webhook."},
|
|
484
516
|
)
|
|
485
517
|
return self
|
|
486
518
|
|
|
@@ -550,6 +582,15 @@ class ChartHint(BaseModel):
|
|
|
550
582
|
)
|
|
551
583
|
|
|
552
584
|
|
|
585
|
+
class TabHint(BaseModel):
|
|
586
|
+
"""One tab of the result, as the agent's page in Explore lists it: its name and what is on it."""
|
|
587
|
+
|
|
588
|
+
model_config = _HINT
|
|
589
|
+
|
|
590
|
+
name: Annotated[str, Field(max_length=C.MAX_NAME_LENGTH)]
|
|
591
|
+
about: Annotated[str, Field(max_length=C.MAX_LABEL_LENGTH)] | None = None
|
|
592
|
+
|
|
593
|
+
|
|
553
594
|
class DisplaySpec(BaseModel):
|
|
554
595
|
"""How the run's result shows on the page, when the builder wants to say so.
|
|
555
596
|
|
|
@@ -560,6 +601,8 @@ class DisplaySpec(BaseModel):
|
|
|
560
601
|
view: document | report | table | chart | code | files
|
|
561
602
|
field: the result key that is the main thing to show
|
|
562
603
|
chart: {type: line | bar, x: date, y: [reach, likes]}
|
|
604
|
+
tabs: [{name: Overview, about: "Your best options and what they cost"}], the
|
|
605
|
+
result's tabs in order, listed on the agent's page before anyone runs it
|
|
563
606
|
"""
|
|
564
607
|
|
|
565
608
|
model_config = _HINT
|
|
@@ -567,6 +610,7 @@ class DisplaySpec(BaseModel):
|
|
|
567
610
|
view: Annotated[str, Field(max_length=C.MAX_NAME_LENGTH)] | None = None
|
|
568
611
|
field: Annotated[str, Field(max_length=C.MAX_NAME_LENGTH)] | None = None
|
|
569
612
|
chart: ChartHint | None = None
|
|
613
|
+
tabs: Annotated[list[TabHint], Field(max_length=12)] = Field(default_factory=list)
|
|
570
614
|
|
|
571
615
|
|
|
572
616
|
class ChooseOneSpec(BaseModel):
|
{gravity_cli-0.10.0 → gravity_cli-0.11.0}/packages/gravity-schema/schema/manifest.schema.json
RENAMED
|
@@ -301,7 +301,7 @@
|
|
|
301
301
|
"type": "object"
|
|
302
302
|
},
|
|
303
303
|
"DisplaySpec": {
|
|
304
|
-
"description": "How the run's result shows on the page, when the builder wants to say so.\n\nA hint, not a rule: without it the page reads the result's own shape, and a\nvalue the page doesn't know (a typo, a newer view) is ignored the same way,\nso it never fails a push or a run.\n\n view: document | report | table | chart | code | files\n field: the result key that is the main thing to show\n chart: {type: line | bar, x: date, y: [reach, likes]}",
|
|
304
|
+
"description": "How the run's result shows on the page, when the builder wants to say so.\n\nA hint, not a rule: without it the page reads the result's own shape, and a\nvalue the page doesn't know (a typo, a newer view) is ignored the same way,\nso it never fails a push or a run.\n\n view: document | report | table | chart | code | files\n field: the result key that is the main thing to show\n chart: {type: line | bar, x: date, y: [reach, likes]}\n tabs: [{name: Overview, about: \"Your best options and what they cost\"}], the\n result's tabs in order, listed on the agent's page before anyone runs it",
|
|
305
305
|
"properties": {
|
|
306
306
|
"chart": {
|
|
307
307
|
"anyOf": [
|
|
@@ -327,6 +327,14 @@
|
|
|
327
327
|
"default": null,
|
|
328
328
|
"title": "Field"
|
|
329
329
|
},
|
|
330
|
+
"tabs": {
|
|
331
|
+
"items": {
|
|
332
|
+
"$ref": "#/$defs/TabHint"
|
|
333
|
+
},
|
|
334
|
+
"maxItems": 12,
|
|
335
|
+
"title": "Tabs",
|
|
336
|
+
"type": "array"
|
|
337
|
+
},
|
|
330
338
|
"view": {
|
|
331
339
|
"anyOf": [
|
|
332
340
|
{
|
|
@@ -344,6 +352,28 @@
|
|
|
344
352
|
"title": "DisplaySpec",
|
|
345
353
|
"type": "object"
|
|
346
354
|
},
|
|
355
|
+
"EmailTriggerSpec": {
|
|
356
|
+
"additionalProperties": false,
|
|
357
|
+
"description": "Run when new mail matching a Gmail search arrives in the person's inbox. Gravity checks every 5 minutes and\nstarts a run only when there is new mail, with the messages in inputs[\"event\"][\"emails\"].",
|
|
358
|
+
"properties": {
|
|
359
|
+
"consumer_can_change": {
|
|
360
|
+
"default": true,
|
|
361
|
+
"title": "Consumer Can Change",
|
|
362
|
+
"type": "boolean"
|
|
363
|
+
},
|
|
364
|
+
"query": {
|
|
365
|
+
"maxLength": 500,
|
|
366
|
+
"minLength": 1,
|
|
367
|
+
"title": "Query",
|
|
368
|
+
"type": "string"
|
|
369
|
+
}
|
|
370
|
+
},
|
|
371
|
+
"required": [
|
|
372
|
+
"query"
|
|
373
|
+
],
|
|
374
|
+
"title": "EmailTriggerSpec",
|
|
375
|
+
"type": "object"
|
|
376
|
+
},
|
|
347
377
|
"InputSpec": {
|
|
348
378
|
"additionalProperties": false,
|
|
349
379
|
"description": "One value the consumer supplies. Renders as one form field.",
|
|
@@ -523,7 +553,9 @@
|
|
|
523
553
|
"secret",
|
|
524
554
|
"file",
|
|
525
555
|
"multi-select",
|
|
526
|
-
"action-choice"
|
|
556
|
+
"action-choice",
|
|
557
|
+
"google-doc",
|
|
558
|
+
"google-sheet"
|
|
527
559
|
],
|
|
528
560
|
"title": "InputType",
|
|
529
561
|
"type": "string"
|
|
@@ -1034,7 +1066,9 @@
|
|
|
1034
1066
|
"markdown",
|
|
1035
1067
|
"docx",
|
|
1036
1068
|
"pptx",
|
|
1037
|
-
"
|
|
1069
|
+
"pdf",
|
|
1070
|
+
"rows",
|
|
1071
|
+
"xlsx"
|
|
1038
1072
|
],
|
|
1039
1073
|
"title": "Renderer",
|
|
1040
1074
|
"type": "string"
|
|
@@ -1339,10 +1373,49 @@
|
|
|
1339
1373
|
"title": "StateSpec",
|
|
1340
1374
|
"type": "object"
|
|
1341
1375
|
},
|
|
1376
|
+
"TabHint": {
|
|
1377
|
+
"description": "One tab of the result, as the agent's page in Explore lists it: its name and what is on it.",
|
|
1378
|
+
"properties": {
|
|
1379
|
+
"about": {
|
|
1380
|
+
"anyOf": [
|
|
1381
|
+
{
|
|
1382
|
+
"maxLength": 200,
|
|
1383
|
+
"type": "string"
|
|
1384
|
+
},
|
|
1385
|
+
{
|
|
1386
|
+
"type": "null"
|
|
1387
|
+
}
|
|
1388
|
+
],
|
|
1389
|
+
"default": null,
|
|
1390
|
+
"title": "About"
|
|
1391
|
+
},
|
|
1392
|
+
"name": {
|
|
1393
|
+
"maxLength": 64,
|
|
1394
|
+
"title": "Name",
|
|
1395
|
+
"type": "string"
|
|
1396
|
+
}
|
|
1397
|
+
},
|
|
1398
|
+
"required": [
|
|
1399
|
+
"name"
|
|
1400
|
+
],
|
|
1401
|
+
"title": "TabHint",
|
|
1402
|
+
"type": "object"
|
|
1403
|
+
},
|
|
1342
1404
|
"TriggersSpec": {
|
|
1343
1405
|
"additionalProperties": false,
|
|
1344
1406
|
"description": "What starts a run. Declared so the consumer sees it before installing.",
|
|
1345
1407
|
"properties": {
|
|
1408
|
+
"email": {
|
|
1409
|
+
"anyOf": [
|
|
1410
|
+
{
|
|
1411
|
+
"$ref": "#/$defs/EmailTriggerSpec"
|
|
1412
|
+
},
|
|
1413
|
+
{
|
|
1414
|
+
"type": "null"
|
|
1415
|
+
}
|
|
1416
|
+
],
|
|
1417
|
+
"default": null
|
|
1418
|
+
},
|
|
1346
1419
|
"manual": {
|
|
1347
1420
|
"default": true,
|
|
1348
1421
|
"title": "Manual",
|
|
@@ -765,6 +765,14 @@ def test_display_hint_parses(manifest_data):
|
|
|
765
765
|
assert (d.view, d.field, d.chart.x, d.chart.y) == ("chart", "daily", "date", ["reach"])
|
|
766
766
|
|
|
767
767
|
|
|
768
|
+
def test_display_tabs_parse_and_survive_the_dump(manifest_data):
|
|
769
|
+
# The push sends model_dump, so the tabs must be in it for the catalog to list them.
|
|
770
|
+
manifest_data["display"] = {"tabs": [{"name": "Overview", "about": "Your best options"}, {"name": "Money"}]}
|
|
771
|
+
d = validate_manifest(manifest_data).display
|
|
772
|
+
assert [t.name for t in d.tabs] == ["Overview", "Money"]
|
|
773
|
+
assert validate_manifest(manifest_data).model_dump(mode="json", exclude_none=True)["display"]["tabs"][0] == {"name": "Overview", "about": "Your best options"}
|
|
774
|
+
|
|
775
|
+
|
|
768
776
|
def test_display_never_fails_on_what_the_page_does_not_know(manifest_data):
|
|
769
777
|
# An unknown view is kept for the page to ignore; an unknown key is dropped.
|
|
770
778
|
manifest_data["display"] = {"view": "carousel", "colour": "blue"}
|
|
@@ -97,3 +97,42 @@ def test_a_date_with_max_takes_several_days():
|
|
|
97
97
|
manifest = validate_manifest(_with(inputs=inputs, choose_one=[]))
|
|
98
98
|
days, deadline = manifest.inputs
|
|
99
99
|
assert days.many_days and not deadline.many_days
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def test_a_file_with_max_takes_several_files():
|
|
103
|
+
inputs = [{"name": "resumes", "label": "Resumes", "type": "file", "accept": ["pdf"], "max": 20},
|
|
104
|
+
{"name": "jd", "label": "Job description", "type": "file"}]
|
|
105
|
+
resumes, jd = validate_manifest(_with(inputs=inputs, choose_one=[])).inputs
|
|
106
|
+
assert resumes.many_files and not jd.many_files
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
@pytest.mark.parametrize("bad", [{"min": 2}, {"min": 3, "max": 2}, {"max": 21}])
|
|
110
|
+
def test_a_file_asks_for_a_sensible_number_of_files(bad):
|
|
111
|
+
with pytest.raises(ManifestValidationError):
|
|
112
|
+
validate_manifest(_with(inputs=[{"name": "f", "label": "F", "type": "file", **bad}], choose_one=[]))
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def test_a_google_doc_or_sheet_link_becomes_the_file_id():
|
|
116
|
+
from gravity_schema.rules import google_file_id
|
|
117
|
+
|
|
118
|
+
fid = "1AbCdEfGhIjKlMnOpQrStUvWxYz0123456789"
|
|
119
|
+
assert google_file_id("google-sheet", f" https://docs.google.com/spreadsheets/d/{fid}/edit#gid=0 ") == fid
|
|
120
|
+
assert google_file_id("google-doc", f"https://docs.google.com/document/d/{fid}/edit?usp=sharing") == fid
|
|
121
|
+
assert google_file_id("google-doc", fid) == fid # a bare id is taken as it is
|
|
122
|
+
assert google_file_id("google-doc", f"https://docs.google.com/spreadsheets/d/{fid}/edit") is None # a Sheet is not a Doc
|
|
123
|
+
for bad in ("my budget sheet", "https://example.com/d/x", None, 7):
|
|
124
|
+
assert google_file_id("google-sheet", bad) is None
|
|
125
|
+
inputs = [{"name": "sheet", "label": "Your sheet", "type": "google-sheet", "required": True}]
|
|
126
|
+
assert validate_manifest(_with(inputs=inputs, choose_one=[])).inputs[0].type.value == "google-sheet"
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
def test_an_email_trigger_watches_gmail_with_the_agents_own_permission():
|
|
130
|
+
m = validate_manifest(_with(inputs=[], choose_one=[], permissions={"tools": ["gmail.read"]},
|
|
131
|
+
triggers={"manual": True, "email": {"query": "from:recruiting@acme.com"}}))
|
|
132
|
+
assert m.triggers.email.query == "from:recruiting@acme.com" and m.triggers.email.consumer_can_change
|
|
133
|
+
with pytest.raises(ManifestValidationError, match="gmail.read"):
|
|
134
|
+
validate_manifest(_with(inputs=[], choose_one=[], permissions={"tools": []},
|
|
135
|
+
triggers={"manual": True, "email": {"query": "is:unread"}}))
|
|
136
|
+
with pytest.raises(ManifestValidationError):
|
|
137
|
+
validate_manifest(_with(inputs=[], choose_one=[], permissions={"tools": ["gmail.read"]},
|
|
138
|
+
triggers={"manual": True, "email": {"query": ""}}))
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "gravity-cli"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.11.0"
|
|
4
4
|
description = "gravity cli — init, run, and push python agents to the Gravity marketplace"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
license = "Apache-2.0"
|
|
7
7
|
license-files = ["LICENSE", "NOTICE"]
|
|
8
8
|
requires-python = ">=3.12"
|
|
9
9
|
dependencies = [
|
|
10
|
-
"gravity-schema==0.
|
|
10
|
+
"gravity-schema==0.11.0", # released in lockstep: always the same version as this package
|
|
11
11
|
"typer>=0.15.0",
|
|
12
12
|
"httpx>=0.27.0",
|
|
13
13
|
"rich>=13.9.0",
|
|
@@ -352,7 +352,9 @@ outputs:
|
|
|
352
352
|
| `markdown` | A formatted page; also what's emailed | Everything in the corpus |
|
|
353
353
|
| `docx` | A Word document | Title, headings, prose and bullets, facts and tables as tables, notes as an italic read-out, a Sources list |
|
|
354
354
|
| `pptx` | A slide deck | A title slide, a Summary slide, then each section as slides (about 10 lines per slide, continued as "(cont.)"), each table on its own slide, `notes` as speaker notes, a Sources slide |
|
|
355
|
+
| `pdf` | A PDF | The same as `docx`, laid out for print; text outside Latin-1 (other scripts, emoji) shows as `?` for now |
|
|
355
356
|
| `rows` | A CSV file | **The first table** in the corpus. Without a table there's nothing to export |
|
|
357
|
+
| `xlsx` | An Excel workbook | **Every table**, one sheet each named after its section. Without a table there's nothing to export |
|
|
356
358
|
|
|
357
359
|
**`kind`** tells Gravity how the agent behaves:
|
|
358
360
|
- `transform`: all input at the start, a result at the end (a report from a file). Gravity
|
|
@@ -127,7 +127,7 @@ resources:
|
|
|
127
127
|
```yaml
|
|
128
128
|
outputs:
|
|
129
129
|
digest:
|
|
130
|
-
renderer: markdown # markdown | docx | pptx | rows
|
|
130
|
+
renderer: markdown # markdown | docx | pptx | pdf | rows | xlsx
|
|
131
131
|
label: "The digest"
|
|
132
132
|
destinations: [download, message.send]
|
|
133
133
|
default: {destination: message.send, app: gmail}
|