keystone-cli 0.3.0__tar.gz → 0.4.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.
- keystone_cli-0.4.0/PKG-INFO +95 -0
- keystone_cli-0.4.0/README.md +74 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/pyproject.toml +16 -6
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/__main__.py +4 -1
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/commands/agent.py +6 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/runner.py +53 -1
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/scaffold.py +5 -0
- keystone_cli-0.4.0/src/keystone_cli/templates/data-space/README.md.tmpl +53 -0
- keystone_cli-0.4.0/src/keystone_cli/templates/data-space/agent.yaml.tmpl +25 -0
- keystone_cli-0.4.0/src/keystone_cli/templates/data-space/pkg/graph.py.tmpl +120 -0
- keystone_cli-0.4.0/src/keystone_cli/templates/data-space/pyproject.toml.tmpl +24 -0
- keystone_cli-0.4.0/src/keystone_cli/templates/data-space/tests/test_graph.py.tmpl +130 -0
- keystone_cli-0.4.0/src/keystone_cli/templates/tool-agent/env.tmpl +10 -0
- keystone_cli-0.4.0/src/keystone_cli/templates/tool-agent/gitignore.tmpl +7 -0
- keystone_cli-0.4.0/src/keystone_cli/templates/tool-agent/pkg/__init__.py.tmpl +0 -0
- keystone_cli-0.4.0/src/keystone_cli/templates/tool-agent/tests/conftest.py.tmpl +25 -0
- keystone_cli-0.4.0/src/keystone_cli/templates/ui-card/README.md.tmpl +49 -0
- keystone_cli-0.4.0/src/keystone_cli/templates/ui-card/agent.yaml.tmpl +19 -0
- keystone_cli-0.4.0/src/keystone_cli/templates/ui-card/env.tmpl +10 -0
- keystone_cli-0.4.0/src/keystone_cli/templates/ui-card/gitignore.tmpl +7 -0
- keystone_cli-0.4.0/src/keystone_cli/templates/ui-card/pkg/__init__.py.tmpl +0 -0
- keystone_cli-0.4.0/src/keystone_cli/templates/ui-card/pkg/graph.py.tmpl +170 -0
- keystone_cli-0.4.0/src/keystone_cli/templates/ui-card/pyproject.toml.tmpl +24 -0
- keystone_cli-0.4.0/src/keystone_cli/templates/ui-card/tests/conftest.py.tmpl +25 -0
- keystone_cli-0.4.0/src/keystone_cli/templates/ui-card/tests/test_graph.py.tmpl +73 -0
- keystone_cli-0.4.0/src/keystone_cli/templates/user-tools/README.md.tmpl +54 -0
- keystone_cli-0.4.0/src/keystone_cli/templates/user-tools/agent.yaml.tmpl +25 -0
- keystone_cli-0.4.0/src/keystone_cli/templates/user-tools/env.tmpl +10 -0
- keystone_cli-0.4.0/src/keystone_cli/templates/user-tools/gitignore.tmpl +7 -0
- keystone_cli-0.4.0/src/keystone_cli/templates/user-tools/pkg/__init__.py.tmpl +0 -0
- keystone_cli-0.4.0/src/keystone_cli/templates/user-tools/pkg/graph.py.tmpl +101 -0
- keystone_cli-0.4.0/src/keystone_cli/templates/user-tools/pyproject.toml.tmpl +25 -0
- keystone_cli-0.4.0/src/keystone_cli/templates/user-tools/tests/conftest.py.tmpl +25 -0
- keystone_cli-0.4.0/src/keystone_cli/templates/user-tools/tests/test_graph.py.tmpl +117 -0
- keystone_cli-0.4.0/src/keystone_cli.egg-info/PKG-INFO +95 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli.egg-info/SOURCES.txt +28 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli.egg-info/requires.txt +1 -1
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/tests/test_doctor.py +25 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/tests/test_init.py +6 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/tests/test_offline.py +55 -0
- keystone_cli-0.3.0/PKG-INFO +0 -15
- keystone_cli-0.3.0/src/keystone_cli.egg-info/PKG-INFO +0 -15
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/setup.cfg +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/__init__.py +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/_build_env.py +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/_jsonout.py +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/_stdio.py +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/_tls.py +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/_version.py +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/agent_logs.py +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/agent_skills.py +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/auth/__init__.py +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/auth/device_flow.py +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/auth/token_store.py +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/commands/__init__.py +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/commands/dev.py +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/commands/kb.py +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/commands/kb_metadata.py +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/commands/login.py +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/commands/prompt.py +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/commands/skills.py +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/commands/tool_credentials.py +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/commands/whoami.py +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/commands/workspace.py +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/devloop.py +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/fetch.py +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/manifest_ref.py +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/platform_client.py +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/run_debug.py +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/skills/keystone-debug/SKILL.md +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/blank/README.md.tmpl +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/blank/agent.yaml.tmpl +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/blank/env.tmpl +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/blank/gitignore.tmpl +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/blank/pkg/__init__.py.tmpl +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/blank/pkg/graph.py.tmpl +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/blank/pyproject.toml.tmpl +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/blank/tests/conftest.py.tmpl +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/blank/tests/test_graph.py.tmpl +0 -0
- {keystone_cli-0.3.0/src/keystone_cli/templates/guardrails → keystone_cli-0.4.0/src/keystone_cli/templates/data-space}/env.tmpl +0 -0
- {keystone_cli-0.3.0/src/keystone_cli/templates/guardrails → keystone_cli-0.4.0/src/keystone_cli/templates/data-space}/gitignore.tmpl +0 -0
- {keystone_cli-0.3.0/src/keystone_cli/templates/guardrails → keystone_cli-0.4.0/src/keystone_cli/templates/data-space}/pkg/__init__.py.tmpl +0 -0
- {keystone_cli-0.3.0/src/keystone_cli/templates/guardrails → keystone_cli-0.4.0/src/keystone_cli/templates/data-space}/tests/conftest.py.tmpl +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/guardrails/README.md.tmpl +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/guardrails/agent.yaml.tmpl +0 -0
- {keystone_cli-0.3.0/src/keystone_cli/templates/hitl → keystone_cli-0.4.0/src/keystone_cli/templates/guardrails}/env.tmpl +0 -0
- {keystone_cli-0.3.0/src/keystone_cli/templates/hitl → keystone_cli-0.4.0/src/keystone_cli/templates/guardrails}/gitignore.tmpl +0 -0
- {keystone_cli-0.3.0/src/keystone_cli/templates/hitl → keystone_cli-0.4.0/src/keystone_cli/templates/guardrails}/pkg/__init__.py.tmpl +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/guardrails/pkg/graph.py.tmpl +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/guardrails/pyproject.toml.tmpl +0 -0
- {keystone_cli-0.3.0/src/keystone_cli/templates/hitl → keystone_cli-0.4.0/src/keystone_cli/templates/guardrails}/tests/conftest.py.tmpl +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/guardrails/tests/test_graph.py.tmpl +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/hitl/README.md.tmpl +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/hitl/agent.yaml.tmpl +0 -0
- {keystone_cli-0.3.0/src/keystone_cli/templates/kb-builder → keystone_cli-0.4.0/src/keystone_cli/templates/hitl}/env.tmpl +0 -0
- {keystone_cli-0.3.0/src/keystone_cli/templates/kb-builder → keystone_cli-0.4.0/src/keystone_cli/templates/hitl}/gitignore.tmpl +0 -0
- {keystone_cli-0.3.0/src/keystone_cli/templates/kb-builder → keystone_cli-0.4.0/src/keystone_cli/templates/hitl}/pkg/__init__.py.tmpl +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/hitl/pkg/graph.py.tmpl +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/hitl/pyproject.toml.tmpl +0 -0
- {keystone_cli-0.3.0/src/keystone_cli/templates/kb-builder → keystone_cli-0.4.0/src/keystone_cli/templates/hitl}/tests/conftest.py.tmpl +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/hitl/tests/test_graph.py.tmpl +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/kb-builder/README.md.tmpl +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/kb-builder/agent.yaml.tmpl +0 -0
- {keystone_cli-0.3.0/src/keystone_cli/templates/llm-streaming → keystone_cli-0.4.0/src/keystone_cli/templates/kb-builder}/env.tmpl +0 -0
- {keystone_cli-0.3.0/src/keystone_cli/templates/llm-streaming → keystone_cli-0.4.0/src/keystone_cli/templates/kb-builder}/gitignore.tmpl +0 -0
- {keystone_cli-0.3.0/src/keystone_cli/templates/llm-streaming → keystone_cli-0.4.0/src/keystone_cli/templates/kb-builder}/pkg/__init__.py.tmpl +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/kb-builder/pkg/graph.py.tmpl +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/kb-builder/pyproject.toml.tmpl +0 -0
- {keystone_cli-0.3.0/src/keystone_cli/templates/llm-streaming → keystone_cli-0.4.0/src/keystone_cli/templates/kb-builder}/tests/conftest.py.tmpl +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/kb-builder/tests/test_graph.py.tmpl +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/llm/README.md.tmpl +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/llm/agent.yaml.tmpl +0 -0
- {keystone_cli-0.3.0/src/keystone_cli/templates/memory-service → keystone_cli-0.4.0/src/keystone_cli/templates/llm}/env.tmpl +0 -0
- {keystone_cli-0.3.0/src/keystone_cli/templates/memory-service → keystone_cli-0.4.0/src/keystone_cli/templates/llm}/gitignore.tmpl +0 -0
- {keystone_cli-0.3.0/src/keystone_cli/templates/memory-service → keystone_cli-0.4.0/src/keystone_cli/templates/llm}/pkg/__init__.py.tmpl +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/llm/pkg/graph.py.tmpl +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/llm/pyproject.toml.tmpl +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/llm/system-prompt.txt.tmpl +0 -0
- {keystone_cli-0.3.0/src/keystone_cli/templates/memory-service → keystone_cli-0.4.0/src/keystone_cli/templates/llm}/tests/conftest.py.tmpl +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/llm/tests/test_graph.py.tmpl +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/llm-streaming/README.md.tmpl +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/llm-streaming/agent.yaml.tmpl +0 -0
- {keystone_cli-0.3.0/src/keystone_cli/templates/llm → keystone_cli-0.4.0/src/keystone_cli/templates/llm-streaming}/env.tmpl +0 -0
- {keystone_cli-0.3.0/src/keystone_cli/templates/llm → keystone_cli-0.4.0/src/keystone_cli/templates/llm-streaming}/gitignore.tmpl +0 -0
- {keystone_cli-0.3.0/src/keystone_cli/templates/llm → keystone_cli-0.4.0/src/keystone_cli/templates/llm-streaming}/pkg/__init__.py.tmpl +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/llm-streaming/pkg/graph.py.tmpl +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/llm-streaming/pyproject.toml.tmpl +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/llm-streaming/system-prompt.txt.tmpl +0 -0
- {keystone_cli-0.3.0/src/keystone_cli/templates/llm → keystone_cli-0.4.0/src/keystone_cli/templates/llm-streaming}/tests/conftest.py.tmpl +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/llm-streaming/tests/test_graph.py.tmpl +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/memory/README.md.tmpl +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/memory/agent.yaml.tmpl +0 -0
- {keystone_cli-0.3.0/src/keystone_cli/templates/ocr → keystone_cli-0.4.0/src/keystone_cli/templates/memory}/env.tmpl +0 -0
- {keystone_cli-0.3.0/src/keystone_cli/templates/ocr → keystone_cli-0.4.0/src/keystone_cli/templates/memory}/gitignore.tmpl +0 -0
- {keystone_cli-0.3.0/src/keystone_cli/templates/ocr → keystone_cli-0.4.0/src/keystone_cli/templates/memory}/pkg/__init__.py.tmpl +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/memory/pkg/graph.py.tmpl +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/memory/pyproject.toml.tmpl +0 -0
- {keystone_cli-0.3.0/src/keystone_cli/templates/ocr → keystone_cli-0.4.0/src/keystone_cli/templates/memory}/tests/conftest.py.tmpl +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/memory/tests/test_graph.py.tmpl +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/memory-service/README.md.tmpl +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/memory-service/agent.yaml.tmpl +0 -0
- {keystone_cli-0.3.0/src/keystone_cli/templates/memory → keystone_cli-0.4.0/src/keystone_cli/templates/memory-service}/env.tmpl +0 -0
- {keystone_cli-0.3.0/src/keystone_cli/templates/memory → keystone_cli-0.4.0/src/keystone_cli/templates/memory-service}/gitignore.tmpl +0 -0
- {keystone_cli-0.3.0/src/keystone_cli/templates/memory → keystone_cli-0.4.0/src/keystone_cli/templates/memory-service}/pkg/__init__.py.tmpl +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/memory-service/pkg/graph.py.tmpl +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/memory-service/pyproject.toml.tmpl +0 -0
- {keystone_cli-0.3.0/src/keystone_cli/templates/memory → keystone_cli-0.4.0/src/keystone_cli/templates/memory-service}/tests/conftest.py.tmpl +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/memory-service/tests/test_graph.py.tmpl +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/ocr/README.md.tmpl +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/ocr/agent.yaml.tmpl +0 -0
- {keystone_cli-0.3.0/src/keystone_cli/templates/rag-qa → keystone_cli-0.4.0/src/keystone_cli/templates/ocr}/env.tmpl +0 -0
- {keystone_cli-0.3.0/src/keystone_cli/templates/rag-qa → keystone_cli-0.4.0/src/keystone_cli/templates/ocr}/gitignore.tmpl +0 -0
- {keystone_cli-0.3.0/src/keystone_cli/templates/rag-qa → keystone_cli-0.4.0/src/keystone_cli/templates/ocr}/pkg/__init__.py.tmpl +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/ocr/pkg/graph.py.tmpl +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/ocr/pyproject.toml.tmpl +0 -0
- {keystone_cli-0.3.0/src/keystone_cli/templates/rag-qa → keystone_cli-0.4.0/src/keystone_cli/templates/ocr}/tests/conftest.py.tmpl +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/ocr/tests/test_graph.py.tmpl +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/rag-qa/README.md.tmpl +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/rag-qa/agent.yaml.tmpl +0 -0
- {keystone_cli-0.3.0/src/keystone_cli/templates/skill → keystone_cli-0.4.0/src/keystone_cli/templates/rag-qa}/env.tmpl +0 -0
- {keystone_cli-0.3.0/src/keystone_cli/templates/skill → keystone_cli-0.4.0/src/keystone_cli/templates/rag-qa}/gitignore.tmpl +0 -0
- {keystone_cli-0.3.0/src/keystone_cli/templates/skill → keystone_cli-0.4.0/src/keystone_cli/templates/rag-qa}/pkg/__init__.py.tmpl +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/rag-qa/pkg/graph.py.tmpl +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/rag-qa/pyproject.toml.tmpl +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/rag-qa/system-prompt.txt.tmpl +0 -0
- {keystone_cli-0.3.0/src/keystone_cli/templates/skill → keystone_cli-0.4.0/src/keystone_cli/templates/rag-qa}/tests/conftest.py.tmpl +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/rag-qa/tests/test_graph.py.tmpl +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/skill/README.md.tmpl +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/skill/agent.yaml.tmpl +0 -0
- {keystone_cli-0.3.0/src/keystone_cli/templates/tool-agent → keystone_cli-0.4.0/src/keystone_cli/templates/skill}/env.tmpl +0 -0
- {keystone_cli-0.3.0/src/keystone_cli/templates/tool-agent → keystone_cli-0.4.0/src/keystone_cli/templates/skill}/gitignore.tmpl +0 -0
- {keystone_cli-0.3.0/src/keystone_cli/templates/tool-agent → keystone_cli-0.4.0/src/keystone_cli/templates/skill}/pkg/__init__.py.tmpl +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/skill/pkg/graph.py.tmpl +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/skill/pyproject.toml.tmpl +0 -0
- {keystone_cli-0.3.0/src/keystone_cli/templates/tool-agent → keystone_cli-0.4.0/src/keystone_cli/templates/skill}/tests/conftest.py.tmpl +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/skill/tests/test_graph.py.tmpl +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/tool-agent/README.md.tmpl +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/tool-agent/agent.yaml.tmpl +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/tool-agent/pkg/graph.py.tmpl +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/tool-agent/pyproject.toml.tmpl +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/tool-agent/system-prompt.txt.tmpl +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/tool-agent/tests/test_graph.py.tmpl +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli.egg-info/dependency_links.txt +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli.egg-info/entry_points.txt +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli.egg-info/top_level.txt +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/tests/test_agent.py +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/tests/test_agent_manifest_cmd.py +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/tests/test_agent_test_cmd.py +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/tests/test_assistant_provenance_and_flags.py +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/tests/test_auth.py +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/tests/test_build_progress.py +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/tests/test_ci_token.py +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/tests/test_config_env_mismatch.py +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/tests/test_deploy.py +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/tests/test_dev.py +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/tests/test_encoding.py +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/tests/test_fetch.py +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/tests/test_help_quality.py +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/tests/test_hitl_approver_cli.py +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/tests/test_hitl_decisions_cli.py +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/tests/test_invoke.py +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/tests/test_invoke_stream.py +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/tests/test_json_output.py +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/tests/test_jsonout.py +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/tests/test_kb_commands.py +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/tests/test_kb_metadata_commands.py +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/tests/test_login_command.py +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/tests/test_logs.py +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/tests/test_platform_client.py +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/tests/test_prompt_commands.py +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/tests/test_publish.py +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/tests/test_retire_delete.py +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/tests/test_run_debug.py +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/tests/test_runs.py +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/tests/test_skills.py +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/tests/test_status.py +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/tests/test_stdio.py +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/tests/test_template_prompt_guard.py +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/tests/test_template_unit_tests.py +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/tests/test_threads.py +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/tests/test_tls.py +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/tests/test_tool_credentials.py +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/tests/test_traces.py +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/tests/test_version.py +0 -0
- {keystone_cli-0.3.0 → keystone_cli-0.4.0}/tests/test_workspace.py +0 -0
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: keystone-cli
|
|
3
|
+
Version: 0.4.0
|
|
4
|
+
Summary: Keystone CLI — build, test, deploy and operate pro-code agents, and manage knowledge bases, prompts, tool credentials and skills on the Keystone platform.
|
|
5
|
+
Classifier: Programming Language :: Python :: 3
|
|
6
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
7
|
+
Classifier: Environment :: Console
|
|
8
|
+
Classifier: Operating System :: OS Independent
|
|
9
|
+
Requires-Python: >=3.12
|
|
10
|
+
Description-Content-Type: text/markdown
|
|
11
|
+
Requires-Dist: keystone-agent-sdk<0.14,>=0.13.20
|
|
12
|
+
Requires-Dist: keystone-request-context<0.4,>=0.3
|
|
13
|
+
Requires-Dist: typer<1,>=0.12
|
|
14
|
+
Requires-Dist: httpx<1,>=0.27
|
|
15
|
+
Requires-Dist: truststore<1,>=0.10
|
|
16
|
+
Requires-Dist: pytest<9,>=8
|
|
17
|
+
Provides-Extra: dev
|
|
18
|
+
Requires-Dist: pytest<9,>=8; extra == "dev"
|
|
19
|
+
Requires-Dist: pytest-cov<7,>=6; extra == "dev"
|
|
20
|
+
Requires-Dist: ruff==0.15.15; extra == "dev"
|
|
21
|
+
|
|
22
|
+
# keystone-cli
|
|
23
|
+
|
|
24
|
+
`keystone` is the command-line tool of the Keystone platform. Use it to build, test, deploy and operate
|
|
25
|
+
pro-code agents. You can also manage knowledge bases, prompts, tool credentials and skills with it.
|
|
26
|
+
|
|
27
|
+
The CLI includes the Keystone agent SDK (`keystone-agent-sdk`). An agent project that you create with
|
|
28
|
+
the CLI uses that SDK.
|
|
29
|
+
|
|
30
|
+
## Install
|
|
31
|
+
|
|
32
|
+
The CLI needs Python 3.12 or later.
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
pip install keystone-cli
|
|
36
|
+
keystone --version
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Get started
|
|
40
|
+
|
|
41
|
+
1. Log in. The command opens your browser and keeps your session for later commands.
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
keystone login
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
2. Select the workspace that your commands use.
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
keystone workspace use <name>
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
3. Create an agent project from a template, then check it.
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
keystone agent init my-agent --template llm
|
|
57
|
+
keystone agent validate my-agent
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
4. Run the unit tests of the agent on your computer.
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
keystone agent test my-agent
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
5. Deploy the agent, make the new version Live, and call it.
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
keystone agent deploy my-agent --publish --wait
|
|
70
|
+
keystone agent invoke my-agent --input '{"prompt": "hi"}'
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
To see the fields of `agent.yaml`, run `keystone agent manifest`. Every command has `--help`.
|
|
74
|
+
|
|
75
|
+
## Commands
|
|
76
|
+
|
|
77
|
+
| Command | What it does |
|
|
78
|
+
| --- | --- |
|
|
79
|
+
| `keystone login`, `keystone whoami` | Log in, and show your user. |
|
|
80
|
+
| `keystone workspace` | List and select the workspace that your commands use. |
|
|
81
|
+
| `keystone agent` | Develop and test an agent locally (`init`, `validate`, `run`, `test`, `manifest`), ship it (`deploy`, `publish`, `status`, `retire`, `delete`), and operate and debug it (`invoke`, `logs`, `fetch`, `doctor`, `runs`, `hitl`, `traces`, `threads`). |
|
|
82
|
+
| `keystone dev` | Run the graph of the agent locally again each time you save a file. |
|
|
83
|
+
| `keystone kb` | Create and manage knowledge bases. |
|
|
84
|
+
| `keystone prompt` | Manage the prompts of a workspace. |
|
|
85
|
+
| `keystone tool-credentials` | Manage the credentials that the catalogue tools of your agents use. |
|
|
86
|
+
| `keystone skills` | Install Claude Code skills for work on agents. |
|
|
87
|
+
| `keystone version` | Show the CLI version, the target environment and the version of the bundled agent SDK. |
|
|
88
|
+
|
|
89
|
+
## When a run fails
|
|
90
|
+
|
|
91
|
+
Start with this command. It shows the steps, the errors and the logs of one run.
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
keystone agent runs debug <agent> <run_id>
|
|
95
|
+
```
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# keystone-cli
|
|
2
|
+
|
|
3
|
+
`keystone` is the command-line tool of the Keystone platform. Use it to build, test, deploy and operate
|
|
4
|
+
pro-code agents. You can also manage knowledge bases, prompts, tool credentials and skills with it.
|
|
5
|
+
|
|
6
|
+
The CLI includes the Keystone agent SDK (`keystone-agent-sdk`). An agent project that you create with
|
|
7
|
+
the CLI uses that SDK.
|
|
8
|
+
|
|
9
|
+
## Install
|
|
10
|
+
|
|
11
|
+
The CLI needs Python 3.12 or later.
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
pip install keystone-cli
|
|
15
|
+
keystone --version
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Get started
|
|
19
|
+
|
|
20
|
+
1. Log in. The command opens your browser and keeps your session for later commands.
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
keystone login
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
2. Select the workspace that your commands use.
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
keystone workspace use <name>
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
3. Create an agent project from a template, then check it.
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
keystone agent init my-agent --template llm
|
|
36
|
+
keystone agent validate my-agent
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
4. Run the unit tests of the agent on your computer.
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
keystone agent test my-agent
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
5. Deploy the agent, make the new version Live, and call it.
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
keystone agent deploy my-agent --publish --wait
|
|
49
|
+
keystone agent invoke my-agent --input '{"prompt": "hi"}'
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
To see the fields of `agent.yaml`, run `keystone agent manifest`. Every command has `--help`.
|
|
53
|
+
|
|
54
|
+
## Commands
|
|
55
|
+
|
|
56
|
+
| Command | What it does |
|
|
57
|
+
| --- | --- |
|
|
58
|
+
| `keystone login`, `keystone whoami` | Log in, and show your user. |
|
|
59
|
+
| `keystone workspace` | List and select the workspace that your commands use. |
|
|
60
|
+
| `keystone agent` | Develop and test an agent locally (`init`, `validate`, `run`, `test`, `manifest`), ship it (`deploy`, `publish`, `status`, `retire`, `delete`), and operate and debug it (`invoke`, `logs`, `fetch`, `doctor`, `runs`, `hitl`, `traces`, `threads`). |
|
|
61
|
+
| `keystone dev` | Run the graph of the agent locally again each time you save a file. |
|
|
62
|
+
| `keystone kb` | Create and manage knowledge bases. |
|
|
63
|
+
| `keystone prompt` | Manage the prompts of a workspace. |
|
|
64
|
+
| `keystone tool-credentials` | Manage the credentials that the catalogue tools of your agents use. |
|
|
65
|
+
| `keystone skills` | Install Claude Code skills for work on agents. |
|
|
66
|
+
| `keystone version` | Show the CLI version, the target environment and the version of the bundled agent SDK. |
|
|
67
|
+
|
|
68
|
+
## When a run fails
|
|
69
|
+
|
|
70
|
+
Start with this command. It shows the steps, the errors and the logs of one run.
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
keystone agent runs debug <agent> <run_id>
|
|
74
|
+
```
|
|
@@ -4,13 +4,23 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "keystone-cli"
|
|
7
|
-
version = "0.
|
|
8
|
-
description = "Keystone
|
|
7
|
+
version = "0.4.0"
|
|
8
|
+
description = "Keystone CLI — build, test, deploy and operate pro-code agents, and manage knowledge bases, prompts, tool credentials and skills on the Keystone platform."
|
|
9
|
+
# The PyPI project page shows this file (it had no description before 0.4.0). It is public: no internal
|
|
10
|
+
# hosts, entity ids or workspace ids in it.
|
|
11
|
+
readme = "README.md"
|
|
9
12
|
requires-python = ">=3.12"
|
|
13
|
+
classifiers = [
|
|
14
|
+
"Programming Language :: Python :: 3",
|
|
15
|
+
"Programming Language :: Python :: 3.12",
|
|
16
|
+
"Environment :: Console",
|
|
17
|
+
"Operating System :: OS Independent",
|
|
18
|
+
]
|
|
10
19
|
dependencies = [
|
|
11
20
|
# Pinned to a compatible range: on an index (Artifact Registry) an unpinned name resolves to
|
|
12
21
|
# ANY published version — the wheel's metadata is the only pin that travels with it.
|
|
13
|
-
|
|
22
|
+
# 0.4.0 needs 0.13.20: the file client of FDP-6964 and the A2UI chat blocks of FDP-7060.
|
|
23
|
+
"keystone-agent-sdk>=0.13.20,<0.14",
|
|
14
24
|
# Transitive (the SDK's building-block clients) + used directly by `run` to set a local
|
|
15
25
|
# caller-identity ContextVar and to patch the clients for --offline. uv sources are NOT
|
|
16
26
|
# transitive, so declare it directly (cf. services/llm-gateway).
|
|
@@ -34,8 +44,8 @@ dev = [
|
|
|
34
44
|
]
|
|
35
45
|
|
|
36
46
|
# The `keystone` command (binary) — `typer.Typer` instances are callable, so the entry points
|
|
37
|
-
# straight at the app.
|
|
38
|
-
# from the repo
|
|
47
|
+
# straight at the app. Published to PyPI as `keystone-cli` (prod) and to Artifact Registry per env
|
|
48
|
+
# (`keystone-cli-<env>`); from the repo: `uv tool install ./libs/python/keystone-cli`.
|
|
39
49
|
[project.scripts]
|
|
40
50
|
keystone = "keystone_cli.__main__:app"
|
|
41
51
|
|
|
@@ -51,7 +61,7 @@ where = ["src"]
|
|
|
51
61
|
keystone_cli = ["templates/*/*.tmpl", "templates/*/pkg/*.tmpl", "templates/*/tests/*.tmpl", "skills/*/SKILL.md"]
|
|
52
62
|
|
|
53
63
|
[tool.ruff]
|
|
54
|
-
target-version = "0.
|
|
64
|
+
target-version = "0.4.0"
|
|
55
65
|
line-length = 120
|
|
56
66
|
|
|
57
67
|
[tool.ruff.lint]
|
|
@@ -61,7 +61,10 @@ Exit codes:
|
|
|
61
61
|
on stdout and the message on stderr."""
|
|
62
62
|
|
|
63
63
|
app = typer.Typer(
|
|
64
|
-
help=
|
|
64
|
+
help=(
|
|
65
|
+
"Keystone CLI — build, test, deploy and operate pro-code agents, and manage knowledge bases, "
|
|
66
|
+
"prompts, tool credentials and skills."
|
|
67
|
+
),
|
|
65
68
|
epilog=EPILOG,
|
|
66
69
|
no_args_is_help=True,
|
|
67
70
|
add_completion=False,
|
|
@@ -2964,6 +2964,12 @@ _GRANT_NAMESPACE = {
|
|
|
2964
2964
|
# `ocr` once platform v112 is on the env. An agent published before that holds none until it
|
|
2965
2965
|
# is re-published.
|
|
2966
2966
|
"ocr": "ocr:",
|
|
2967
|
+
# Sprint: v8 | Feature: FR-157 OCR in the Pro-code Agent SDK | Task Group: 1.4 | ACs: AC-1240
|
|
2968
|
+
# Contract: agent-hub AgentManifestAclGrants FILE_ARTIFACT_PERMISSIONS | Tracking: FDP-6120
|
|
2969
|
+
# agent-hub mints artifact:create + artifact:read on the workspace from `file-artifact` (FDP-6261),
|
|
2970
|
+
# and an agent that reads a file by reference must declare it (FR-157 AC-08). Without this entry
|
|
2971
|
+
# doctor called it a typo and exited 1 while every call to it worked (FDP-6120 QC, qc 24-10).
|
|
2972
|
+
"file-artifact": "artifact:",
|
|
2967
2973
|
}
|
|
2968
2974
|
#: Every name agent-hub acts on (AgentManifestAclGrants): the ones above plus rag, whose access is
|
|
2969
2975
|
#: the per-KB grant instead of a service-level one. Anything else mints nothing and is not in the
|
|
@@ -458,9 +458,52 @@ _OFFLINE_STUBS: dict[str, dict[str, Any]] = {
|
|
|
458
458
|
),
|
|
459
459
|
# OCR (FDP-5712) — every OcrClient operation. Enveloped like the service; `ocr_list_pages`
|
|
460
460
|
# keeps `pagination` beside `data`.
|
|
461
|
+
# Data Space (FDP-6473) — a SQL space's /ask body, unwrapped (the service sends no envelope).
|
|
462
|
+
"data_space_ask": {
|
|
463
|
+
"sql": "SELECT 1 AS offline_stub",
|
|
464
|
+
"columns": ["offline_stub"],
|
|
465
|
+
"rows": [[1]],
|
|
466
|
+
"row_count": 1,
|
|
467
|
+
"source_tables": [],
|
|
468
|
+
"trace": [],
|
|
469
|
+
"ambiguities": [],
|
|
470
|
+
},
|
|
461
471
|
"ocr_sync_from_url": _enveloped({"pages": [_OFFLINE_OCR_PAGE], "summary": _OFFLINE_OCR_SUMMARY}),
|
|
462
472
|
"ocr_submit_job_from_url": _enveloped({**_OFFLINE_OCR_JOB, "status": "queued", "completed_at": None}),
|
|
473
|
+
# A file-artifact reference (FDP-6120): the same answers, the job's `source` naming what was read.
|
|
474
|
+
"ocr_sync_from_artifact": _enveloped({"pages": [_OFFLINE_OCR_PAGE], "summary": _OFFLINE_OCR_SUMMARY}),
|
|
475
|
+
"ocr_submit_job_from_artifact": _enveloped(
|
|
476
|
+
{
|
|
477
|
+
**_OFFLINE_OCR_JOB,
|
|
478
|
+
"status": "queued",
|
|
479
|
+
"completed_at": None,
|
|
480
|
+
"source": {"type": "file_artifact", "artifact_id": "offline-artifact", "version": 1, "sha256": "0" * 64},
|
|
481
|
+
}
|
|
482
|
+
),
|
|
463
483
|
"ocr_get_job": _enveloped(_OFFLINE_OCR_JOB),
|
|
484
|
+
# The user's attachments (FDP-6261). An offline turn carries none, so these answer only a call
|
|
485
|
+
# an author makes by hand; the shapes are file-artifact's `get_metadata` and `read_artifact`.
|
|
486
|
+
"file_artifact_get_attachment": _enveloped(
|
|
487
|
+
{
|
|
488
|
+
"artifact_id": "offline-artifact",
|
|
489
|
+
"name": "offline.txt",
|
|
490
|
+
"mime": "text/plain",
|
|
491
|
+
"size_bytes": 27,
|
|
492
|
+
"status": "ACTIVE",
|
|
493
|
+
"purpose": "attachment",
|
|
494
|
+
}
|
|
495
|
+
),
|
|
496
|
+
"file_artifact_read_attachment": _enveloped(
|
|
497
|
+
{"artifact_id": "offline-artifact", "version": 1, "mime": "text/plain", "text": "[offline attachment text]"}
|
|
498
|
+
),
|
|
499
|
+
"file_artifact_attachment_url": _enveloped(
|
|
500
|
+
{"artifact_id": "offline-artifact", "download_url": "https://offline.invalid/offline-artifact"}
|
|
501
|
+
),
|
|
502
|
+
# Speech-to-text (FDP-6261): an audio attachment's transcript, short clip or long.
|
|
503
|
+
"audio_transcription": {"text": "[offline transcript]", "duration": 1.0},
|
|
504
|
+
"audio_transcription_job": {"id": "offline-stt-job", "status": "processing"},
|
|
505
|
+
"audio_transcription_job_get": {"id": "offline-stt-job", "status": "completed"},
|
|
506
|
+
"audio_transcription_transcript": {"text": "[offline transcript]"},
|
|
464
507
|
"ocr_cancel_job": _enveloped({**_OFFLINE_OCR_JOB, "status": "cancelled"}),
|
|
465
508
|
"ocr_read_text": _enveloped(
|
|
466
509
|
{
|
|
@@ -640,7 +683,8 @@ def _local_identity() -> Iterator[None]:
|
|
|
640
683
|
def _offline_clients() -> Iterator[None]:
|
|
641
684
|
"""Patch the SDK clients' transport so building-block calls return canned stubs (no network).
|
|
642
685
|
|
|
643
|
-
Patches **every verb** (``_post``, ``_get``, ``_patch``, ``_put``, ``_delete``, ``_post_multipart
|
|
686
|
+
Patches **every verb** (``_post``, ``_get``, ``_patch``, ``_put``, ``_delete``, ``_post_multipart``,
|
|
687
|
+
``_get_bytes``).
|
|
644
688
|
Missing one is not a partial feature: an
|
|
645
689
|
unpatched verb reaches the real network from a mode whose whole promise is "no live services
|
|
646
690
|
or quota", and it does so silently.
|
|
@@ -701,6 +745,11 @@ def _offline_clients() -> Iterator[None]:
|
|
|
701
745
|
async def _stub_get(self: Any, path: str, *, operation: str, **_: Any) -> dict[str, Any]:
|
|
702
746
|
return _stub(operation, path)
|
|
703
747
|
|
|
748
|
+
async def _stub_get_bytes(self: Any, path: str, *, operation: str, **_: Any) -> bytes:
|
|
749
|
+
# FDP-6261: an attachment's bytes. Without it a download left the pod.
|
|
750
|
+
typer.secho(f" [offline] {operation} {path}", fg=typer.colors.YELLOW)
|
|
751
|
+
return b"[offline attachment bytes]"
|
|
752
|
+
|
|
704
753
|
async def _stub_resolve(self: Any, name: str, **_: Any) -> Any:
|
|
705
754
|
# FDP-6465: the prompt read is not a verb of BaseClient (it needs the ETag/304 path), so it
|
|
706
755
|
# is patched on its own. An OUTAGE, not a stub version: aget_prompt then runs on the
|
|
@@ -718,6 +767,7 @@ def _offline_clients() -> Iterator[None]:
|
|
|
718
767
|
_base.BaseClient._put,
|
|
719
768
|
_base.BaseClient._delete,
|
|
720
769
|
_base.BaseClient._post_multipart,
|
|
770
|
+
_base.BaseClient._get_bytes,
|
|
721
771
|
)
|
|
722
772
|
_base.BaseClient._post = _stub_post # type: ignore[method-assign]
|
|
723
773
|
_base.BaseClient._get = _stub_get # type: ignore[method-assign]
|
|
@@ -725,6 +775,7 @@ def _offline_clients() -> Iterator[None]:
|
|
|
725
775
|
_base.BaseClient._put = _stub_put # type: ignore[method-assign]
|
|
726
776
|
_base.BaseClient._delete = _stub_delete # type: ignore[method-assign]
|
|
727
777
|
_base.BaseClient._post_multipart = _stub_multipart # type: ignore[method-assign]
|
|
778
|
+
_base.BaseClient._get_bytes = _stub_get_bytes # type: ignore[method-assign]
|
|
728
779
|
try:
|
|
729
780
|
yield
|
|
730
781
|
finally:
|
|
@@ -735,5 +786,6 @@ def _offline_clients() -> Iterator[None]:
|
|
|
735
786
|
_base.BaseClient._put,
|
|
736
787
|
_base.BaseClient._delete,
|
|
737
788
|
_base.BaseClient._post_multipart,
|
|
789
|
+
_base.BaseClient._get_bytes,
|
|
738
790
|
) = originals # type: ignore[method-assign]
|
|
739
791
|
prompt_hub.PromptHubClient.resolve = original_resolve # type: ignore[method-assign]
|
|
@@ -40,6 +40,11 @@ TEMPLATES = (
|
|
|
40
40
|
"kb-builder",
|
|
41
41
|
# FDP-5712 — OCR a document by signed URL (sync, or as a job read back as text).
|
|
42
42
|
"ocr",
|
|
43
|
+
# FDP-6473 — what an agent does for the END USER of a chat turn: draw a UI component and
|
|
44
|
+
# answer its click, ask a data space as that person, call a tool with that person's sign-in.
|
|
45
|
+
"ui-card",
|
|
46
|
+
"data-space",
|
|
47
|
+
"user-tools",
|
|
43
48
|
)
|
|
44
49
|
|
|
45
50
|
# Agent names double as k8s child-resource names + queue names — keep them DNS-label-safe.
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# __AGENT_NAME__
|
|
2
|
+
|
|
3
|
+
Scaffolded from the **data-space** template. The agent answers questions from one published
|
|
4
|
+
Keystone Data Space, **as the end user of the turn**: the data space applies that person's access.
|
|
5
|
+
|
|
6
|
+
## Set it up
|
|
7
|
+
|
|
8
|
+
1. Publish a data space in your workspace, and copy its id.
|
|
9
|
+
2. In `agent.yaml`, put the id in `dependencies.data_spaces` **and** in
|
|
10
|
+
`config.RT_AGENT_DATA_SPACE_ID`.
|
|
11
|
+
- `data_spaces` makes agent-hub grant the agent `data-space:read` and `data-space:query` on
|
|
12
|
+
the space at publish.
|
|
13
|
+
- `data-space-runtime` in `dependencies.services` scopes the invocation key to the data space
|
|
14
|
+
service. Do not remove it.
|
|
15
|
+
3. Deploy: `keystone agent deploy . --publish`.
|
|
16
|
+
|
|
17
|
+
## What the user sees
|
|
18
|
+
|
|
19
|
+
- An answer: the summary (NDP space) and the first rows as a table.
|
|
20
|
+
- **Sign-in needed**: when the space has an Access Grant and the user has not signed in with an
|
|
21
|
+
Auth Client that it accepts, `ask` raises `SignInRequired`. The graph calls
|
|
22
|
+
`request_sign_in(exc)`, and the chat shows the sign-in card. After the sign-in, the next
|
|
23
|
+
question can succeed.
|
|
24
|
+
- **No access**: when the user is not in the space's Access Grant and no Auth Client can change
|
|
25
|
+
that, `ask` raises `BuildingBlockForbiddenError` (a `SignInRequired` is a subclass, so catch
|
|
26
|
+
that first). The agent tells the user. An uncaught error fails the run, and the Front Desk
|
|
27
|
+
master then shows "no answer".
|
|
28
|
+
- A refusal that the space gives (it cannot plan the question, the space is not available): the
|
|
29
|
+
agent tells the user and does not retry. Each question costs a model call.
|
|
30
|
+
|
|
31
|
+
## Known limits
|
|
32
|
+
|
|
33
|
+
- The data space can run with the agent-grant check off (`DS_CONSUMER_ACCESS_ENFORCED`). In an
|
|
34
|
+
environment where it is off, a space that the manifest does not declare can still answer. Do
|
|
35
|
+
not rely on that: declare every space.
|
|
36
|
+
|
|
37
|
+
## Local loop
|
|
38
|
+
```bash
|
|
39
|
+
keystone agent validate .
|
|
40
|
+
keystone agent run . --input '{"messages": [{"role": "user", "content": "How many orders this month?"}]}' --offline
|
|
41
|
+
keystone agent test .
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
`--offline` answers every question with a stub row; no data space is called.
|
|
45
|
+
|
|
46
|
+
## Unit tests
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
keystone agent test .
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
`use_client("get_data_space_client", fake)` puts a fake in place of the data space. The fake
|
|
53
|
+
needs only `ask`. Raise `SignInRequired` from it to test the sign-in path.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# bundle-rev: 0001 — bump this string to force a rebuild (agent-hub dedups identical bundles by SHA-256)
|
|
2
|
+
# __AGENT_NAME__ — scaffolded by `keystone agent init` (template: data-space).
|
|
3
|
+
# A chat agent that answers questions from a Keystone Data Space, as the end user of the turn.
|
|
4
|
+
# Local loop:
|
|
5
|
+
# keystone agent validate .
|
|
6
|
+
# keystone agent run . --input '{"messages": [{"role": "user", "content": "How many orders this month?"}]}' --offline
|
|
7
|
+
# keystone agent test
|
|
8
|
+
name: __AGENT_NAME__
|
|
9
|
+
workspace: __WORKSPACE__
|
|
10
|
+
framework: langgraph@1
|
|
11
|
+
entrypoint: __PKG__.graph:make_graph
|
|
12
|
+
runtime: python3.12
|
|
13
|
+
resources:
|
|
14
|
+
# One answer plans, runs and summarises a query: give it time.
|
|
15
|
+
timeout_seconds: 180
|
|
16
|
+
dependencies:
|
|
17
|
+
# `data-space-runtime` scopes the run's invocation key to the data space service. Without it
|
|
18
|
+
# every ask is refused before it reaches the space.
|
|
19
|
+
services: [data-space-runtime]
|
|
20
|
+
# The PUBLISHED data spaces this agent asks (UUIDs). agent-hub grants the agent
|
|
21
|
+
# data-space:read + data-space:query on each one at publish. Replace the zero UUID with yours,
|
|
22
|
+
# here AND in config below.
|
|
23
|
+
data_spaces: ["00000000-0000-0000-0000-000000000000"]
|
|
24
|
+
config:
|
|
25
|
+
RT_AGENT_DATA_SPACE_ID: "00000000-0000-0000-0000-000000000000"
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
"""__AGENT_NAME__ — answer from a Keystone Data Space, as the end user of the turn (FDP-6473).
|
|
2
|
+
|
|
3
|
+
One node:
|
|
4
|
+
|
|
5
|
+
1. Ask the published data space the user's question with ``DataSpaceClient.ask``. The call goes
|
|
6
|
+
through the platform gateway with the run's invocation key, so the data space sees the agent
|
|
7
|
+
AND the end user, and applies the end user's access.
|
|
8
|
+
2. When the space has an Access Grant and the user has not signed in with an Auth Client it
|
|
9
|
+
accepts, ``ask`` raises ``SignInRequired``. Show the sign-in card with ``request_sign_in`` and
|
|
10
|
+
tell the user. Do not answer as though the space had no data.
|
|
11
|
+
Any other 403 (``BuildingBlockForbiddenError``: the user is not in the space's Access Grant and
|
|
12
|
+
no sign-in can change that, or the agent has no grant on the space) is told to the user too.
|
|
13
|
+
Catch ``SignInRequired`` first: it is a subclass. An uncaught error fails the run, and a
|
|
14
|
+
caller such as the Front Desk master then shows "no answer".
|
|
15
|
+
3. A refusal that the space answers inside a normal reply (an unavailable space, a question it
|
|
16
|
+
cannot plan) is ``answer.error``: tell the user, do not retry. A question costs a model call.
|
|
17
|
+
|
|
18
|
+
The state keeps the questions and their SQL in ``history``, so a follow-up question ("and last
|
|
19
|
+
month?") is read in context. The data space reads the last 10 turns.
|
|
20
|
+
|
|
21
|
+
Local loop:
|
|
22
|
+
keystone agent run . --input '{"messages": [{"role": "user", "content": "How many orders this month?"}]}' --offline
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
from __future__ import annotations
|
|
26
|
+
|
|
27
|
+
import os
|
|
28
|
+
from typing import Annotated, Any, TypedDict
|
|
29
|
+
|
|
30
|
+
from keystone.agent_sdk.clients import (
|
|
31
|
+
BuildingBlockForbiddenError,
|
|
32
|
+
DataSpaceAnswer,
|
|
33
|
+
SignInRequired,
|
|
34
|
+
get_data_space_client,
|
|
35
|
+
)
|
|
36
|
+
from keystone.agent_sdk.ui import request_sign_in
|
|
37
|
+
from langchain_core.messages import AIMessage, AnyMessage, HumanMessage
|
|
38
|
+
from langgraph.graph import StateGraph
|
|
39
|
+
from langgraph.graph.message import add_messages
|
|
40
|
+
|
|
41
|
+
#: Rows shown in the chat. The answer keeps all of them in ``answer.rows``.
|
|
42
|
+
MAX_ROWS = 10
|
|
43
|
+
|
|
44
|
+
SIGN_IN_REPLY = "You must sign in to see this data. Use the sign-in card, then ask again."
|
|
45
|
+
NO_ACCESS_REPLY = "You do not have access to this data space. Ask its owner for access."
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
class State(TypedDict, total=False):
|
|
49
|
+
messages: Annotated[list[AnyMessage], add_messages]
|
|
50
|
+
# Earlier questions of this conversation, for follow-ups: [{"question", "sql"}].
|
|
51
|
+
history: list[dict[str, Any]]
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def _space_id() -> str:
|
|
55
|
+
space = os.environ.get("RT_AGENT_DATA_SPACE_ID", "").strip()
|
|
56
|
+
if not space:
|
|
57
|
+
raise RuntimeError("RT_AGENT_DATA_SPACE_ID is empty — set it under `config:` in agent.yaml")
|
|
58
|
+
return space
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def _question(state: State) -> str:
|
|
62
|
+
for message in reversed(state.get("messages") or []):
|
|
63
|
+
if isinstance(message, HumanMessage) and isinstance(message.content, str):
|
|
64
|
+
return message.content.strip()
|
|
65
|
+
return ""
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def format_answer(answer: DataSpaceAnswer) -> str:
|
|
69
|
+
"""The answer as chat text: the summary (NDP space), then the first rows as a table."""
|
|
70
|
+
parts: list[str] = []
|
|
71
|
+
if answer.summary:
|
|
72
|
+
parts.append(answer.summary)
|
|
73
|
+
if answer.rows:
|
|
74
|
+
parts.append(_table(answer.columns, answer.rows[:MAX_ROWS]))
|
|
75
|
+
if len(answer.rows) > MAX_ROWS:
|
|
76
|
+
parts.append(f"(first {MAX_ROWS} of {len(answer.rows)} rows)")
|
|
77
|
+
if not parts:
|
|
78
|
+
parts.append("The data space found no rows for this question.")
|
|
79
|
+
return "\n\n".join(parts)
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def _table(columns: list[Any], rows: list[Any]) -> str:
|
|
83
|
+
# A SQL space sends rows as lists; an NDP space as objects.
|
|
84
|
+
names = [str(c.get("name") if isinstance(c, dict) else c) for c in columns]
|
|
85
|
+
if not names and rows and isinstance(rows[0], dict):
|
|
86
|
+
names = list(rows[0])
|
|
87
|
+
lines = ["| " + " | ".join(names) + " |", "|" + "---|" * len(names)]
|
|
88
|
+
for row in rows:
|
|
89
|
+
cells = [row.get(n) for n in names] if isinstance(row, dict) else list(row)
|
|
90
|
+
lines.append("| " + " | ".join("" if v is None else str(v) for v in cells) + " |")
|
|
91
|
+
return "\n".join(lines)
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
async def ask(state: State) -> dict[str, Any]:
|
|
95
|
+
question = _question(state)
|
|
96
|
+
if not question:
|
|
97
|
+
return {"messages": [AIMessage("Ask me a question about the data.")]}
|
|
98
|
+
history = list(state.get("history") or [])
|
|
99
|
+
try:
|
|
100
|
+
answer = await get_data_space_client().ask(_space_id(), question, history=history)
|
|
101
|
+
except SignInRequired as exc:
|
|
102
|
+
request_sign_in(exc) # the sign-in card, on every surface
|
|
103
|
+
return {"messages": [AIMessage(SIGN_IN_REPLY)]}
|
|
104
|
+
except BuildingBlockForbiddenError:
|
|
105
|
+
# A refusal that no sign-in can change. Answer it: a failed run reads as "the agent is down".
|
|
106
|
+
return {"messages": [AIMessage(NO_ACCESS_REPLY)]}
|
|
107
|
+
if not answer.ok:
|
|
108
|
+
error = answer.error or {}
|
|
109
|
+
reason = error.get("message") or error.get("code") or "unknown reason"
|
|
110
|
+
return {"messages": [AIMessage(f"The data space could not answer this question: {reason}")]}
|
|
111
|
+
history.append({"question": question, "sql": answer.sql})
|
|
112
|
+
return {"messages": [AIMessage(format_answer(answer))], "history": history}
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def make_graph():
|
|
116
|
+
g = StateGraph(State)
|
|
117
|
+
g.add_node("ask", ask)
|
|
118
|
+
g.set_entry_point("ask")
|
|
119
|
+
g.set_finish_point("ask")
|
|
120
|
+
return g
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "__AGENT_NAME__"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
requires-python = ">=3.12"
|
|
5
|
+
# Declared for humans/IDEs: the DEPLOYED image is built FROM the platform base image,
|
|
6
|
+
# which already bakes keystone-agent-sdk + langgraph — the server-side (Kaniko) build
|
|
7
|
+
# copies your code only, it does NOT pip-install. Locally, `keystone agent validate/run`
|
|
8
|
+
# execute in the CLI's own environment.
|
|
9
|
+
dependencies = [
|
|
10
|
+
# >=0.13.15: DataSpaceClient, SignInRequired and ui.request_sign_in landed there.
|
|
11
|
+
"keystone-agent-sdk>=0.13.15",
|
|
12
|
+
"langgraph>=1,<2",
|
|
13
|
+
"langchain-core>=1,<2",
|
|
14
|
+
]
|
|
15
|
+
|
|
16
|
+
# Unit tests: `keystone agent test` runs tests/ in the CLI's environment. `uv run pytest` installs
|
|
17
|
+
# this group and runs them in the project's own environment (for an agent with its own libraries).
|
|
18
|
+
[dependency-groups]
|
|
19
|
+
dev = ["pytest>=8,<9", "anyio>=4", "keystone-agent-sdk>=0.13.15"]
|
|
20
|
+
|
|
21
|
+
[tool.pytest.ini_options]
|
|
22
|
+
testpaths = ["tests"]
|
|
23
|
+
pythonpath = ["."]
|
|
24
|
+
addopts = "-ra --strict-markers"
|