venn-cli 0.1.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.
- venn_cli-0.1.0/.github/workflows/ci.yml +25 -0
- venn_cli-0.1.0/.github/workflows/publish-pypi.yaml +30 -0
- venn_cli-0.1.0/.gitignore +8 -0
- venn_cli-0.1.0/LICENSE +21 -0
- venn_cli-0.1.0/PKG-INFO +27 -0
- venn_cli-0.1.0/VERSION +1 -0
- venn_cli-0.1.0/docs/openapi.json +1 -0
- venn_cli-0.1.0/pyproject.toml +52 -0
- venn_cli-0.1.0/src/venn_cli/__init__.py +0 -0
- venn_cli-0.1.0/src/venn_cli/cli.py +265 -0
- venn_cli-0.1.0/src/venn_cli/client.py +165 -0
- venn_cli-0.1.0/src/venn_cli/output.py +167 -0
- venn_cli-0.1.0/tests/__init__.py +0 -0
- venn_cli-0.1.0/tests/conftest.py +61 -0
- venn_cli-0.1.0/tests/test_cli.py +308 -0
- venn_cli-0.1.0/tests/test_client.py +295 -0
- venn_cli-0.1.0/tests/test_integration.py +229 -0
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
unit-tests:
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
strategy:
|
|
12
|
+
matrix:
|
|
13
|
+
python-version: ["3.12", "3.13"]
|
|
14
|
+
steps:
|
|
15
|
+
- uses: actions/checkout@v4
|
|
16
|
+
|
|
17
|
+
- uses: actions/setup-python@v5
|
|
18
|
+
with:
|
|
19
|
+
python-version: ${{ matrix.python-version }}
|
|
20
|
+
|
|
21
|
+
- name: Install dependencies
|
|
22
|
+
run: pip install -e ".[dev]"
|
|
23
|
+
|
|
24
|
+
- name: Run unit tests
|
|
25
|
+
run: pytest -m "not integration" -v
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- "v*"
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
contents: read
|
|
10
|
+
id-token: write
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
publish:
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
environment: pypi
|
|
16
|
+
steps:
|
|
17
|
+
- uses: actions/checkout@v4
|
|
18
|
+
|
|
19
|
+
- uses: actions/setup-python@v5
|
|
20
|
+
with:
|
|
21
|
+
python-version: "3.13"
|
|
22
|
+
|
|
23
|
+
- name: Install build tools
|
|
24
|
+
run: pip install build
|
|
25
|
+
|
|
26
|
+
- name: Build package
|
|
27
|
+
run: python -m build
|
|
28
|
+
|
|
29
|
+
- name: Publish to PyPI
|
|
30
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
venn_cli-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Moda Labs
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
venn_cli-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: venn-cli
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: CLI for the Venn ToolIQ API
|
|
5
|
+
Project-URL: Homepage, https://github.com/moda-labs/venn-cli
|
|
6
|
+
Project-URL: Repository, https://github.com/moda-labs/venn-cli
|
|
7
|
+
Project-URL: Issues, https://github.com/moda-labs/venn-cli/issues
|
|
8
|
+
Author-email: Moda Labs <zach@modalabs.ai>
|
|
9
|
+
License-Expression: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Classifier: Development Status :: 3 - Alpha
|
|
12
|
+
Classifier: Environment :: Console
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
19
|
+
Classifier: Topic :: Software Development
|
|
20
|
+
Requires-Python: >=3.11
|
|
21
|
+
Requires-Dist: click>=8.1
|
|
22
|
+
Requires-Dist: httpx>=0.27
|
|
23
|
+
Requires-Dist: python-dotenv>=1.0
|
|
24
|
+
Requires-Dist: rich>=13.0
|
|
25
|
+
Provides-Extra: dev
|
|
26
|
+
Requires-Dist: pytest>=8.0; extra == 'dev'
|
|
27
|
+
Requires-Dist: respx>=0.22; extra == 'dev'
|
venn_cli-0.1.0/VERSION
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
0.1.0
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"openapi":"3.1.0","info":{"title":"ToolIQ REST API","description":"REST API for tool discovery, search, and execution","version":"1.0.0"},"paths":{"/tools/list":{"get":{"summary":"Api List All Tools","description":"List all tools for a server with metadata. Requires one of: slug, directory_id, or instance_id. Returns server name, version, and tool metadata.","operationId":"api_list_all_tools_tools_list_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"directory_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Server directory UUID","title":"Directory Id"},"description":"Server directory UUID"},{"name":"instance_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Server instance UUID","title":"Instance Id"},"description":"Server instance UUID"},{"name":"slug","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Toolset slug (e.g., 'salesforce', 'gmail')","title":"Slug"},"description":"Toolset slug (e.g., 'salesforce', 'gmail')"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListToolsSuccessResponse"}}}},"400":{"description":"Invalid request parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Server not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/tools/search":{"post":{"summary":"Api Search Tools","description":"Search for tools across connected MCP servers using semantic similarity. Returns ranked results with scores, supports pagination and filtering.","operationId":"api_search_tools_tools_search_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchToolsRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchToolsSuccessResponse"}}}},"400":{"description":"Invalid request parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"HTTPBearer":[]}]}},"/tools/describe":{"post":{"summary":"Api Describe Tools","description":"Get detailed schema information for one or more tools including inputSchema, description, and write operation metadata.","operationId":"api_describe_tools_tools_describe_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DescribeToolsRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DescribeToolsSuccessResponse"}}}},"400":{"description":"Invalid request or tool not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Tool not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/tools/execute":{"post":{"summary":"Api Execute Tool","description":"Execute a specific tool on a connected MCP server. Supports audit operations with confirmation tokens.","operationId":"api_execute_tool_tools_execute_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExecuteToolRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExecuteToolSuccessResponse"}}}},"400":{"description":"Invalid request or execution failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Server not connected","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/tools/execute-workflow":{"post":{"summary":"Api Execute Code","description":"Execute Python code in a sandboxed environment for programmatic tool calling with access to async_call_tool() and async_call_skill() (call sites must `await`).","operationId":"api_execute_code_tools_execute_workflow_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExecuteCodeRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExecuteCodeSuccessResponse"}}}},"400":{"description":"Invalid request or code execution failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"408":{"description":"Code execution timeout","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/tools/help":{"post":{"summary":"Api Help","description":"Get help information, server status, and authentication URLs. Supports actions: getting_started, connector_help, auth_helper, list_servers.","operationId":"api_help_tools_help_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HelpRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HelpSuccessResponse"}}}},"400":{"description":"Invalid action or request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/tools/confirm":{"post":{"summary":"Api Confirm Write Operation","description":"Get a confirmation token for executing write operations.\n\nRequest body: {} (no parameters required)\n\nAuthentication:\n Requires Bearer token in Authorization header","operationId":"api_confirm_write_operation_tools_confirm_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConfirmWriteOperationSuccessResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"HTTPBearer":[]}]}},"/skills":{"post":{"summary":"Api Upsert Skill","description":"Create or update an executable skill. Writes the YAML to disk and reloads the index.\n\nThis endpoint is intended for local development use (e.g., from the create-skill CLI command).\nDeployed environments must opt in explicitly with TOOL_ROUTER_SKILL_UPSERT_ENABLED.","operationId":"api_upsert_skill_skills_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpsertSkillRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"401":{"description":"Authentication required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Endpoint disabled","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"400":{"description":"Invalid skill YAML","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/toolset/{toolset_key}/history":{"get":{"summary":"Api List Catalog History","description":"Catalog (YAML) history for a 1st-party toolset, newest first.","operationId":"api_list_catalog_history_toolset__toolset_key__history_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"toolset_key","in":"path","required":true,"schema":{"type":"string","title":"Toolset Key"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":50,"title":"Limit"}},{"name":"before_version","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","minimum":0},{"type":"null"}],"title":"Before Version"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CatalogHistorySuccessResponse"}}}},"404":{"description":"Toolset has no catalog history","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"History unavailable — DB temporarily unreachable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/server/{directory_id}/history":{"get":{"summary":"Api List Server History","description":"Per-server-instance history, newest first. Works for any connected\nserver including 3rd-party — caller must supply `directory_id`.","operationId":"api_list_server_history_server__directory_id__history_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"directory_id","in":"path","required":true,"schema":{"type":"string","title":"Directory Id"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":50,"title":"Limit"}},{"name":"before_version","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","minimum":0},{"type":"null"}],"title":"Before Version"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServerHistorySuccessResponse"}}}},"404":{"description":"No history for this directory_id","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"History unavailable — DB temporarily unreachable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}}},"components":{"schemas":{"CatalogHistoryData":{"properties":{"toolset_key":{"type":"string","title":"Toolset Key"},"revisions":{"items":{"$ref":"#/components/schemas/RevisionSummary"},"type":"array","title":"Revisions"}},"type":"object","required":["toolset_key","revisions"],"title":"CatalogHistoryData","description":"Data returned by /toolset/{toolset_key}/history endpoint."},"CatalogHistorySuccessResponse":{"properties":{"success":{"type":"boolean","const":true,"title":"Success","default":true},"version":{"type":"string","title":"Version"},"result":{"$ref":"#/components/schemas/CatalogHistoryData"}},"type":"object","required":["result"],"title":"CatalogHistorySuccessResponse","description":"Success response for /toolset/{toolset_key}/history."},"ConfirmWriteOperationData":{"properties":{"confirmation_token":{"type":"string","title":"Confirmation Token"},"expires_in_seconds":{"type":"integer","title":"Expires In Seconds"},"usage":{"type":"string","title":"Usage"},"important":{"type":"string","title":"Important"}},"type":"object","required":["confirmation_token","expires_in_seconds","usage","important"],"title":"ConfirmWriteOperationData","description":"Data returned by confirm_write_operation endpoint."},"ConfirmWriteOperationSuccessResponse":{"properties":{"success":{"type":"boolean","const":true,"title":"Success","default":true},"version":{"type":"string","title":"Version"},"result":{"$ref":"#/components/schemas/ConfirmWriteOperationData"}},"type":"object","required":["result"],"title":"ConfirmWriteOperationSuccessResponse","description":"Success response for /tools/confirm endpoint."},"DescribeToolsData":{"properties":{"results":{"items":{"$ref":"#/components/schemas/ToolDetailsData"},"type":"array","title":"Results"}},"type":"object","required":["results"],"title":"DescribeToolsData","description":"Data returned by describe_tools endpoint."},"DescribeToolsRequest":{"properties":{"tools":{"items":{"$ref":"#/components/schemas/ToolIdentifier"},"type":"array","title":"Tools","description":"List of tool identifiers"},"refresh":{"type":"boolean","title":"Refresh","description":"Bypass cache","default":false}},"type":"object","required":["tools"],"title":"DescribeToolsRequest"},"DescribeToolsSuccessResponse":{"properties":{"success":{"type":"boolean","const":true,"title":"Success","default":true},"version":{"type":"string","title":"Version"},"result":{"$ref":"#/components/schemas/DescribeToolsData"}},"type":"object","required":["result"],"title":"DescribeToolsSuccessResponse","description":"Success response for /tools/describe endpoint."},"ErrorResponse":{"properties":{"success":{"type":"boolean","const":false,"title":"Success","default":false},"version":{"type":"string","title":"Version"},"error":{"anyOf":[{"type":"string"},{"additionalProperties":true,"type":"object"}],"title":"Error","description":"Error message or structured error details"}},"type":"object","required":["error"],"title":"ErrorResponse","description":"Response model for error responses."},"ExecuteCodeData":{"properties":{"result":{"title":"Result"}},"type":"object","required":["result"],"title":"ExecuteCodeData","description":"Data returned by execute_code endpoint."},"ExecuteCodeRequest":{"properties":{"code":{"type":"string","title":"Code","description":"Python code to execute"},"timeout":{"type":"integer","maximum":360.0,"minimum":1.0,"title":"Timeout","description":"Maximum execution time in seconds","default":180},"confirmed":{"type":"boolean","title":"Confirmed","description":"For write operations, set to True after user approval","default":false},"confirmation_token":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Confirmation Token","description":"Required when confirmed=True"}},"type":"object","required":["code"],"title":"ExecuteCodeRequest"},"ExecuteCodeSuccessResponse":{"properties":{"success":{"type":"boolean","const":true,"title":"Success","default":true},"version":{"type":"string","title":"Version"},"result":{"$ref":"#/components/schemas/ExecuteCodeData"}},"type":"object","required":["result"],"title":"ExecuteCodeSuccessResponse","description":"Success response for /tools/execute-code endpoint."},"ExecuteToolRequest":{"properties":{"server_id":{"type":"string","title":"Server Id","description":"Server identifier"},"tool_name":{"type":"string","title":"Tool Name","description":"Tool name"},"tool_args":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Tool Args","description":"Tool arguments"},"refresh":{"type":"boolean","title":"Refresh","description":"Bypass cache","default":false},"confirmed":{"type":"boolean","title":"Confirmed","description":"For write operations, set to True after user approval","default":false},"confirmation_token":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Confirmation Token","description":"Required when confirmed=True"}},"type":"object","required":["server_id","tool_name"],"title":"ExecuteToolRequest"},"ExecuteToolSuccessResponse":{"properties":{"success":{"type":"boolean","const":true,"title":"Success","default":true},"version":{"type":"string","title":"Version"},"result":{"title":"Result"}},"type":"object","required":["result"],"title":"ExecuteToolSuccessResponse","description":"Success response for /tools/execute endpoint."},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"HelpRequest":{"properties":{"action":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Action","description":"Help action: getting_started, connector_help, auth_helper, list_servers"},"server_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Server Id","description":"Server identifier (required for auth_helper)"},"refresh":{"type":"boolean","title":"Refresh","description":"Bypass cache","default":false}},"type":"object","title":"HelpRequest"},"HelpSuccessResponse":{"properties":{"success":{"type":"boolean","const":true,"title":"Success","default":true},"version":{"type":"string","title":"Version"},"result":{"anyOf":[{"additionalProperties":true,"type":"object"},{"items":{"additionalProperties":true,"type":"object"},"type":"array"}],"title":"Result"}},"type":"object","required":["result"],"title":"HelpSuccessResponse","description":"Success response for /tools/help endpoint."},"ListToolsData":{"properties":{"name":{"type":"string","title":"Name"},"slug":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Slug"},"toolset_version":{"type":"string","title":"Toolset Version"},"tools":{"items":{"$ref":"#/components/schemas/ToolMetadata"},"type":"array","title":"Tools"},"instance_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Instance Id"},"directory_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Directory Id"}},"type":"object","required":["name","slug","toolset_version","tools","instance_id","directory_id"],"title":"ListToolsData","description":"Data returned by list_tools endpoint."},"ListToolsSuccessResponse":{"properties":{"success":{"type":"boolean","const":true,"title":"Success","default":true},"version":{"type":"string","title":"Version"},"result":{"$ref":"#/components/schemas/ListToolsData"}},"type":"object","required":["result"],"title":"ListToolsSuccessResponse","description":"Success response for /tools/list endpoint."},"RevisionSummary":{"properties":{"version":{"type":"integer","title":"Version"},"transaction_id":{"type":"string","title":"Transaction Id"},"issued_at":{"type":"string","format":"date-time","title":"Issued At"},"source":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source"},"summary":{"additionalProperties":{"type":"integer"},"type":"object","title":"Summary"}},"type":"object","required":["version","transaction_id","issued_at","summary"],"title":"RevisionSummary","description":"A single revision in a toolset's or server's history.\n\n`version` is a 0-indexed counter scoped to the slice (toolset_key OR\ndirectory_id; v0 = oldest revision in that slice). `transaction_id` is\nthe underlying global Continuum transaction id, exposed for debugging."},"SearchToolsData":{"properties":{"candidates":{"items":{"anyOf":[{"$ref":"#/components/schemas/ToolCandidate"},{"$ref":"#/components/schemas/SkillCandidate"}]},"type":"array","title":"Candidates"},"total":{"type":"integer","title":"Total"},"limit":{"type":"integer","title":"Limit"},"offset":{"type":"integer","title":"Offset"}},"type":"object","required":["candidates","total","limit","offset"],"title":"SearchToolsData","description":"Data returned by search_tools endpoint.\n\nReturns a unified list of tools and skills ranked by relevance.\nEach candidate has a 'type' field to distinguish between tools and skills."},"SearchToolsRequest":{"properties":{"query":{"type":"string","title":"Query","description":"Search query text"},"limit":{"type":"integer","maximum":100.0,"minimum":1.0,"title":"Limit","description":"Maximum number of results","default":10},"offset":{"type":"integer","minimum":0.0,"title":"Offset","description":"Number of results to skip","default":0},"min_score":{"type":"number","maximum":1.0,"minimum":0.0,"title":"Min Score","description":"Minimum similarity score threshold","default":0.3},"min_results":{"type":"integer","minimum":0.0,"title":"Min Results","description":"Minimum results to return even if below threshold","default":5},"refresh":{"type":"boolean","title":"Refresh","description":"Bypass cache to get updated servers","default":false}},"type":"object","required":["query"],"title":"SearchToolsRequest"},"SearchToolsSuccessResponse":{"properties":{"success":{"type":"boolean","const":true,"title":"Success","default":true},"version":{"type":"string","title":"Version"},"result":{"$ref":"#/components/schemas/SearchToolsData"}},"type":"object","required":["result"],"title":"SearchToolsSuccessResponse","description":"Success response for /tools/search endpoint."},"ServerHistoryData":{"properties":{"directory_id":{"type":"string","title":"Directory Id"},"revisions":{"items":{"$ref":"#/components/schemas/RevisionSummary"},"type":"array","title":"Revisions"}},"type":"object","required":["directory_id","revisions"],"title":"ServerHistoryData","description":"Data returned by /server/{directory_id}/history endpoint."},"ServerHistorySuccessResponse":{"properties":{"success":{"type":"boolean","const":true,"title":"Success","default":true},"version":{"type":"string","title":"Version"},"result":{"$ref":"#/components/schemas/ServerHistoryData"}},"type":"object","required":["result"],"title":"ServerHistorySuccessResponse","description":"Success response for /server/{directory_id}/history."},"SkillCandidate":{"properties":{"type":{"type":"string","const":"skill","title":"Type","default":"skill"},"rank":{"type":"integer","title":"Rank"},"name":{"type":"string","title":"Name"},"description":{"type":"string","title":"Description"}},"type":"object","required":["rank","name","description"],"title":"SkillCandidate","description":"Lightweight skill summary in search results.\n\nReturns minimal information to save context tokens.\nUse describe_skill tool to retrieve full pattern content."},"ToolCandidate":{"properties":{"type":{"type":"string","const":"tool","title":"Type","default":"tool"},"rank":{"type":"integer","title":"Rank"},"server_id":{"type":"string","title":"Server Id"},"server_name":{"type":"string","title":"Server Name"},"tool_name":{"type":"string","title":"Tool Name"},"short_description":{"type":"string","title":"Short Description"},"server_connected":{"type":"boolean","title":"Server Connected"},"annotations":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Annotations"}},"type":"object","required":["rank","server_id","server_name","tool_name","short_description","server_connected"],"title":"ToolCandidate","description":"Individual tool in search results."},"ToolDetailsData":{"properties":{"server_id":{"type":"string","title":"Server Id"},"server_name":{"type":"string","title":"Server Name"},"tool_name":{"type":"string","title":"Tool Name"},"description":{"type":"string","title":"Description"},"extended_description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Extended Description"},"inputSchema":{"additionalProperties":true,"type":"object","title":"Inputschema"},"outputSchema":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Outputschema"},"write_operation":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Write Operation"},"preview_template":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Preview Template"},"annotations":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Annotations"}},"type":"object","required":["server_id","server_name","tool_name","description","inputSchema"],"title":"ToolDetailsData","description":"Detailed schema information for a single tool."},"ToolIdentifier":{"properties":{"server_id":{"type":"string","title":"Server Id","description":"Server identifier"},"tool_name":{"type":"string","title":"Tool Name","description":"Tool name"}},"type":"object","required":["server_id","tool_name"],"title":"ToolIdentifier"},"ToolMetadata":{"properties":{"tool_name":{"type":"string","title":"Tool Name"},"readable_name":{"type":"string","title":"Readable Name"},"short_description":{"type":"string","title":"Short Description"},"crud_operation":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Crud Operation"},"status":{"type":"string","title":"Status"},"risk_level":{"type":"integer","title":"Risk Level"},"audit":{"type":"boolean","title":"Audit"},"paywalled":{"type":"boolean","title":"Paywalled"}},"type":"object","required":["tool_name","readable_name","short_description","crud_operation","status","risk_level","audit","paywalled"],"title":"ToolMetadata","description":"Metadata for a single tool in a toolset."},"UpsertSkillRequest":{"properties":{"content":{"type":"string","title":"Content","description":"Full YAML content of the skill file"}},"type":"object","required":["content"],"title":"UpsertSkillRequest","description":"Request body for POST /skills — create or update an executable skill."},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"}},"securitySchemes":{"HTTPBearer":{"type":"http","description":"JWT Bearer token from Barndoor platform","scheme":"bearer"}}},"servers":[{"url":"/tooliq/api","description":"ToolIQ REST API"}]}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "venn-cli"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "CLI for the Venn ToolIQ API"
|
|
5
|
+
requires-python = ">=3.11"
|
|
6
|
+
license = "MIT"
|
|
7
|
+
authors = [
|
|
8
|
+
{ name = "Moda Labs", email = "zach@modalabs.ai" },
|
|
9
|
+
]
|
|
10
|
+
classifiers = [
|
|
11
|
+
"Development Status :: 3 - Alpha",
|
|
12
|
+
"Environment :: Console",
|
|
13
|
+
"Intended Audience :: Developers",
|
|
14
|
+
"License :: OSI Approved :: MIT License",
|
|
15
|
+
"Programming Language :: Python :: 3",
|
|
16
|
+
"Programming Language :: Python :: 3.11",
|
|
17
|
+
"Programming Language :: Python :: 3.12",
|
|
18
|
+
"Programming Language :: Python :: 3.13",
|
|
19
|
+
"Topic :: Software Development",
|
|
20
|
+
]
|
|
21
|
+
dependencies = [
|
|
22
|
+
"click>=8.1",
|
|
23
|
+
"httpx>=0.27",
|
|
24
|
+
"rich>=13.0",
|
|
25
|
+
"python-dotenv>=1.0",
|
|
26
|
+
]
|
|
27
|
+
|
|
28
|
+
[project.urls]
|
|
29
|
+
Homepage = "https://github.com/moda-labs/venn-cli"
|
|
30
|
+
Repository = "https://github.com/moda-labs/venn-cli"
|
|
31
|
+
Issues = "https://github.com/moda-labs/venn-cli/issues"
|
|
32
|
+
|
|
33
|
+
[project.scripts]
|
|
34
|
+
venn = "venn_cli.cli:main"
|
|
35
|
+
|
|
36
|
+
[project.optional-dependencies]
|
|
37
|
+
dev = [
|
|
38
|
+
"pytest>=8.0",
|
|
39
|
+
"respx>=0.22",
|
|
40
|
+
]
|
|
41
|
+
|
|
42
|
+
[build-system]
|
|
43
|
+
requires = ["hatchling"]
|
|
44
|
+
build-backend = "hatchling.build"
|
|
45
|
+
|
|
46
|
+
[tool.pytest.ini_options]
|
|
47
|
+
markers = [
|
|
48
|
+
"integration: hits the live Venn API (requires VENN_API_KEY)",
|
|
49
|
+
]
|
|
50
|
+
|
|
51
|
+
[tool.hatch.build.targets.wheel]
|
|
52
|
+
packages = ["src/venn_cli"]
|
|
File without changes
|
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
import os
|
|
5
|
+
import sys
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
|
|
8
|
+
import click
|
|
9
|
+
from dotenv import load_dotenv
|
|
10
|
+
|
|
11
|
+
from venn_cli.client import VennClient
|
|
12
|
+
from venn_cli import output
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def _load_env() -> None:
|
|
16
|
+
for p in [Path.cwd() / ".env", Path(__file__).resolve().parents[2] / ".env"]:
|
|
17
|
+
if p.exists():
|
|
18
|
+
load_dotenv(p)
|
|
19
|
+
return
|
|
20
|
+
load_dotenv()
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def _client(ctx: click.Context) -> VennClient:
|
|
24
|
+
return ctx.obj["client"]
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
@click.group()
|
|
28
|
+
@click.option("--api-key", envvar="VENN_API_KEY", help="Venn API key (or set VENN_API_KEY)")
|
|
29
|
+
@click.option("--base-url", envvar="VENN_BASE_URL", default=None, help="Override API base URL")
|
|
30
|
+
@click.option("--raw", is_flag=True, help="Output raw JSON instead of formatted tables")
|
|
31
|
+
@click.version_option(package_name="venn-cli")
|
|
32
|
+
@click.pass_context
|
|
33
|
+
def main(ctx: click.Context, api_key: str | None, base_url: str | None, raw: bool) -> None:
|
|
34
|
+
"""Venn ToolIQ CLI — discover, inspect, and execute tools."""
|
|
35
|
+
_load_env()
|
|
36
|
+
api_key = api_key or os.environ.get("VENN_API_KEY")
|
|
37
|
+
if not api_key:
|
|
38
|
+
click.echo("Error: VENN_API_KEY not set. Pass --api-key or add it to .env", err=True)
|
|
39
|
+
raise SystemExit(1)
|
|
40
|
+
kwargs = {"api_key": api_key}
|
|
41
|
+
if base_url:
|
|
42
|
+
kwargs["base_url"] = base_url
|
|
43
|
+
ctx.ensure_object(dict)
|
|
44
|
+
ctx.obj["client"] = VennClient(**kwargs)
|
|
45
|
+
ctx.obj["raw"] = raw
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
# ---------------------------------------------------------------------------
|
|
49
|
+
# venn tools
|
|
50
|
+
# ---------------------------------------------------------------------------
|
|
51
|
+
|
|
52
|
+
@main.group()
|
|
53
|
+
def tools():
|
|
54
|
+
"""Discover, inspect, and execute tools."""
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
@tools.command("list")
|
|
58
|
+
@click.option("--slug", "-s", help="Toolset slug (e.g. 'salesforce', 'gmail')")
|
|
59
|
+
@click.option("--directory-id", "-d", help="Server directory UUID")
|
|
60
|
+
@click.option("--instance-id", "-i", help="Server instance UUID")
|
|
61
|
+
@click.pass_context
|
|
62
|
+
def tools_list(ctx, slug, directory_id, instance_id):
|
|
63
|
+
"""List tools for a server."""
|
|
64
|
+
if not any([slug, directory_id, instance_id]):
|
|
65
|
+
click.echo("Provide at least one of: --slug, --directory-id, --instance-id", err=True)
|
|
66
|
+
raise SystemExit(1)
|
|
67
|
+
data = _client(ctx).list_tools(slug=slug, directory_id=directory_id, instance_id=instance_id)
|
|
68
|
+
if ctx.obj["raw"]:
|
|
69
|
+
output.print_json(data)
|
|
70
|
+
else:
|
|
71
|
+
output.print_tool_list(data.get("result", {}))
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
@tools.command("search")
|
|
75
|
+
@click.argument("query")
|
|
76
|
+
@click.option("--limit", "-n", default=10, type=int, help="Max results")
|
|
77
|
+
@click.option("--offset", default=0, type=int, help="Skip N results")
|
|
78
|
+
@click.option("--min-score", default=0.3, type=float, help="Minimum similarity score")
|
|
79
|
+
@click.option("--refresh", is_flag=True, help="Bypass cache")
|
|
80
|
+
@click.pass_context
|
|
81
|
+
def tools_search(ctx, query, limit, offset, min_score, refresh):
|
|
82
|
+
"""Search tools by natural language query."""
|
|
83
|
+
data = _client(ctx).search_tools(query, limit=limit, offset=offset, min_score=min_score, refresh=refresh)
|
|
84
|
+
if ctx.obj["raw"]:
|
|
85
|
+
output.print_json(data)
|
|
86
|
+
else:
|
|
87
|
+
output.print_search_results(data.get("result", {}))
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
@tools.command("describe")
|
|
91
|
+
@click.option("--server-id", "-s", required=True, help="Server identifier")
|
|
92
|
+
@click.option("--tool-name", "-t", required=True, multiple=True, help="Tool name (repeatable)")
|
|
93
|
+
@click.option("--refresh", is_flag=True, help="Bypass cache")
|
|
94
|
+
@click.pass_context
|
|
95
|
+
def tools_describe(ctx, server_id, tool_name, refresh):
|
|
96
|
+
"""Get detailed schema for one or more tools."""
|
|
97
|
+
tools_list = [{"server_id": server_id, "tool_name": t} for t in tool_name]
|
|
98
|
+
data = _client(ctx).describe_tools(tools_list, refresh=refresh)
|
|
99
|
+
if ctx.obj["raw"]:
|
|
100
|
+
output.print_json(data)
|
|
101
|
+
else:
|
|
102
|
+
output.print_tool_details(data.get("result", {}).get("results", []))
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
@tools.command("execute")
|
|
106
|
+
@click.option("--server-id", "-s", required=True, help="Server identifier")
|
|
107
|
+
@click.option("--tool-name", "-t", required=True, help="Tool name")
|
|
108
|
+
@click.option("--args", "-a", "tool_args", default=None, help="Tool arguments as JSON string")
|
|
109
|
+
@click.option("--confirm", "do_confirm", is_flag=True, help="Auto-obtain confirmation token for write ops")
|
|
110
|
+
@click.pass_context
|
|
111
|
+
def tools_execute(ctx, server_id, tool_name, tool_args, do_confirm):
|
|
112
|
+
"""Execute a tool."""
|
|
113
|
+
client = _client(ctx)
|
|
114
|
+
parsed_args = json.loads(tool_args) if tool_args else None
|
|
115
|
+
|
|
116
|
+
confirmation_token = None
|
|
117
|
+
if do_confirm:
|
|
118
|
+
confirm_data = client.confirm_write()
|
|
119
|
+
confirmation_token = confirm_data.get("result", {}).get("confirmation_token")
|
|
120
|
+
|
|
121
|
+
data = client.execute_tool(
|
|
122
|
+
server_id=server_id,
|
|
123
|
+
tool_name=tool_name,
|
|
124
|
+
tool_args=parsed_args,
|
|
125
|
+
confirmed=do_confirm,
|
|
126
|
+
confirmation_token=confirmation_token,
|
|
127
|
+
)
|
|
128
|
+
if ctx.obj["raw"]:
|
|
129
|
+
output.print_json(data)
|
|
130
|
+
else:
|
|
131
|
+
output.print_execute_result(data)
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
@tools.command("confirm")
|
|
135
|
+
@click.pass_context
|
|
136
|
+
def tools_confirm(ctx):
|
|
137
|
+
"""Get a confirmation token for write operations."""
|
|
138
|
+
data = _client(ctx).confirm_write()
|
|
139
|
+
if ctx.obj["raw"]:
|
|
140
|
+
output.print_json(data)
|
|
141
|
+
else:
|
|
142
|
+
output.print_confirm(data.get("result", {}))
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
# ---------------------------------------------------------------------------
|
|
146
|
+
# venn workflow
|
|
147
|
+
# ---------------------------------------------------------------------------
|
|
148
|
+
|
|
149
|
+
@main.group()
|
|
150
|
+
def workflow():
|
|
151
|
+
"""Execute code in a sandboxed environment."""
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
@workflow.command("run")
|
|
155
|
+
@click.option("--code", "-c", help="Python code to execute")
|
|
156
|
+
@click.option("--file", "-f", "code_file", type=click.Path(exists=True), help="Read code from file")
|
|
157
|
+
@click.option("--timeout", default=180, type=int, help="Max execution time in seconds")
|
|
158
|
+
@click.option("--confirm", "do_confirm", is_flag=True, help="Obtain confirmation for write ops")
|
|
159
|
+
@click.pass_context
|
|
160
|
+
def workflow_run(ctx, code, code_file, timeout, do_confirm):
|
|
161
|
+
"""Execute Python code in the Venn sandbox."""
|
|
162
|
+
if code_file:
|
|
163
|
+
code = Path(code_file).read_text()
|
|
164
|
+
if not code:
|
|
165
|
+
click.echo("Provide --code or --file", err=True)
|
|
166
|
+
raise SystemExit(1)
|
|
167
|
+
|
|
168
|
+
client = _client(ctx)
|
|
169
|
+
confirmation_token = None
|
|
170
|
+
if do_confirm:
|
|
171
|
+
confirm_data = client.confirm_write()
|
|
172
|
+
confirmation_token = confirm_data.get("result", {}).get("confirmation_token")
|
|
173
|
+
|
|
174
|
+
data = client.execute_workflow(
|
|
175
|
+
code=code,
|
|
176
|
+
timeout=timeout,
|
|
177
|
+
confirmed=do_confirm,
|
|
178
|
+
confirmation_token=confirmation_token,
|
|
179
|
+
)
|
|
180
|
+
if ctx.obj["raw"]:
|
|
181
|
+
output.print_json(data)
|
|
182
|
+
else:
|
|
183
|
+
output.print_execute_result(data)
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
# ---------------------------------------------------------------------------
|
|
187
|
+
# venn help
|
|
188
|
+
# ---------------------------------------------------------------------------
|
|
189
|
+
|
|
190
|
+
@main.command("help")
|
|
191
|
+
@click.argument("action", required=False, type=click.Choice(
|
|
192
|
+
["getting_started", "connector_help", "auth_helper", "list_servers"],
|
|
193
|
+
case_sensitive=False,
|
|
194
|
+
))
|
|
195
|
+
@click.option("--server-id", "-s", help="Server ID (required for auth_helper)")
|
|
196
|
+
@click.option("--refresh", is_flag=True, help="Bypass cache")
|
|
197
|
+
@click.pass_context
|
|
198
|
+
def help_cmd(ctx, action, server_id, refresh):
|
|
199
|
+
"""Get help, server status, or auth URLs."""
|
|
200
|
+
data = _client(ctx).help(action=action, server_id=server_id, refresh=refresh)
|
|
201
|
+
if ctx.obj["raw"]:
|
|
202
|
+
output.print_json(data)
|
|
203
|
+
else:
|
|
204
|
+
output.print_help_result(data.get("result"))
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
# ---------------------------------------------------------------------------
|
|
208
|
+
# venn skills
|
|
209
|
+
# ---------------------------------------------------------------------------
|
|
210
|
+
|
|
211
|
+
@main.group()
|
|
212
|
+
def skills():
|
|
213
|
+
"""Manage executable skills."""
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
@skills.command("upsert")
|
|
217
|
+
@click.option("--file", "-f", "skill_file", required=True, type=click.Path(exists=True), help="Skill YAML file")
|
|
218
|
+
@click.pass_context
|
|
219
|
+
def skills_upsert(ctx, skill_file):
|
|
220
|
+
"""Create or update a skill from a YAML file."""
|
|
221
|
+
content = Path(skill_file).read_text()
|
|
222
|
+
data = _client(ctx).upsert_skill(content)
|
|
223
|
+
if ctx.obj["raw"]:
|
|
224
|
+
output.print_json(data)
|
|
225
|
+
else:
|
|
226
|
+
output.console.print("[green]Skill upserted successfully.[/green]")
|
|
227
|
+
if data.get("result"):
|
|
228
|
+
output.print_json(data["result"])
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
# ---------------------------------------------------------------------------
|
|
232
|
+
# venn history
|
|
233
|
+
# ---------------------------------------------------------------------------
|
|
234
|
+
|
|
235
|
+
@main.group()
|
|
236
|
+
def history():
|
|
237
|
+
"""View catalog and server revision history."""
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
@history.command("toolset")
|
|
241
|
+
@click.argument("toolset_key")
|
|
242
|
+
@click.option("--limit", "-n", default=50, type=int, help="Max revisions")
|
|
243
|
+
@click.option("--before", "before_version", default=None, type=int, help="Only show versions before this")
|
|
244
|
+
@click.pass_context
|
|
245
|
+
def history_toolset(ctx, toolset_key, limit, before_version):
|
|
246
|
+
"""Show revision history for a toolset."""
|
|
247
|
+
data = _client(ctx).toolset_history(toolset_key, limit=limit, before_version=before_version)
|
|
248
|
+
if ctx.obj["raw"]:
|
|
249
|
+
output.print_json(data)
|
|
250
|
+
else:
|
|
251
|
+
output.print_history(data.get("result", {}))
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
@history.command("server")
|
|
255
|
+
@click.argument("directory_id")
|
|
256
|
+
@click.option("--limit", "-n", default=50, type=int, help="Max revisions")
|
|
257
|
+
@click.option("--before", "before_version", default=None, type=int, help="Only show versions before this")
|
|
258
|
+
@click.pass_context
|
|
259
|
+
def history_server(ctx, directory_id, limit, before_version):
|
|
260
|
+
"""Show revision history for a server instance."""
|
|
261
|
+
data = _client(ctx).server_history(directory_id, limit=limit, before_version=before_version)
|
|
262
|
+
if ctx.obj["raw"]:
|
|
263
|
+
output.print_json(data)
|
|
264
|
+
else:
|
|
265
|
+
output.print_history(data.get("result", {}))
|