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.
Files changed (225) hide show
  1. keystone_cli-0.4.0/PKG-INFO +95 -0
  2. keystone_cli-0.4.0/README.md +74 -0
  3. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/pyproject.toml +16 -6
  4. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/__main__.py +4 -1
  5. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/commands/agent.py +6 -0
  6. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/runner.py +53 -1
  7. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/scaffold.py +5 -0
  8. keystone_cli-0.4.0/src/keystone_cli/templates/data-space/README.md.tmpl +53 -0
  9. keystone_cli-0.4.0/src/keystone_cli/templates/data-space/agent.yaml.tmpl +25 -0
  10. keystone_cli-0.4.0/src/keystone_cli/templates/data-space/pkg/graph.py.tmpl +120 -0
  11. keystone_cli-0.4.0/src/keystone_cli/templates/data-space/pyproject.toml.tmpl +24 -0
  12. keystone_cli-0.4.0/src/keystone_cli/templates/data-space/tests/test_graph.py.tmpl +130 -0
  13. keystone_cli-0.4.0/src/keystone_cli/templates/tool-agent/env.tmpl +10 -0
  14. keystone_cli-0.4.0/src/keystone_cli/templates/tool-agent/gitignore.tmpl +7 -0
  15. keystone_cli-0.4.0/src/keystone_cli/templates/tool-agent/pkg/__init__.py.tmpl +0 -0
  16. keystone_cli-0.4.0/src/keystone_cli/templates/tool-agent/tests/conftest.py.tmpl +25 -0
  17. keystone_cli-0.4.0/src/keystone_cli/templates/ui-card/README.md.tmpl +49 -0
  18. keystone_cli-0.4.0/src/keystone_cli/templates/ui-card/agent.yaml.tmpl +19 -0
  19. keystone_cli-0.4.0/src/keystone_cli/templates/ui-card/env.tmpl +10 -0
  20. keystone_cli-0.4.0/src/keystone_cli/templates/ui-card/gitignore.tmpl +7 -0
  21. keystone_cli-0.4.0/src/keystone_cli/templates/ui-card/pkg/__init__.py.tmpl +0 -0
  22. keystone_cli-0.4.0/src/keystone_cli/templates/ui-card/pkg/graph.py.tmpl +170 -0
  23. keystone_cli-0.4.0/src/keystone_cli/templates/ui-card/pyproject.toml.tmpl +24 -0
  24. keystone_cli-0.4.0/src/keystone_cli/templates/ui-card/tests/conftest.py.tmpl +25 -0
  25. keystone_cli-0.4.0/src/keystone_cli/templates/ui-card/tests/test_graph.py.tmpl +73 -0
  26. keystone_cli-0.4.0/src/keystone_cli/templates/user-tools/README.md.tmpl +54 -0
  27. keystone_cli-0.4.0/src/keystone_cli/templates/user-tools/agent.yaml.tmpl +25 -0
  28. keystone_cli-0.4.0/src/keystone_cli/templates/user-tools/env.tmpl +10 -0
  29. keystone_cli-0.4.0/src/keystone_cli/templates/user-tools/gitignore.tmpl +7 -0
  30. keystone_cli-0.4.0/src/keystone_cli/templates/user-tools/pkg/__init__.py.tmpl +0 -0
  31. keystone_cli-0.4.0/src/keystone_cli/templates/user-tools/pkg/graph.py.tmpl +101 -0
  32. keystone_cli-0.4.0/src/keystone_cli/templates/user-tools/pyproject.toml.tmpl +25 -0
  33. keystone_cli-0.4.0/src/keystone_cli/templates/user-tools/tests/conftest.py.tmpl +25 -0
  34. keystone_cli-0.4.0/src/keystone_cli/templates/user-tools/tests/test_graph.py.tmpl +117 -0
  35. keystone_cli-0.4.0/src/keystone_cli.egg-info/PKG-INFO +95 -0
  36. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli.egg-info/SOURCES.txt +28 -0
  37. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli.egg-info/requires.txt +1 -1
  38. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/tests/test_doctor.py +25 -0
  39. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/tests/test_init.py +6 -0
  40. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/tests/test_offline.py +55 -0
  41. keystone_cli-0.3.0/PKG-INFO +0 -15
  42. keystone_cli-0.3.0/src/keystone_cli.egg-info/PKG-INFO +0 -15
  43. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/setup.cfg +0 -0
  44. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/__init__.py +0 -0
  45. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/_build_env.py +0 -0
  46. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/_jsonout.py +0 -0
  47. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/_stdio.py +0 -0
  48. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/_tls.py +0 -0
  49. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/_version.py +0 -0
  50. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/agent_logs.py +0 -0
  51. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/agent_skills.py +0 -0
  52. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/auth/__init__.py +0 -0
  53. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/auth/device_flow.py +0 -0
  54. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/auth/token_store.py +0 -0
  55. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/commands/__init__.py +0 -0
  56. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/commands/dev.py +0 -0
  57. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/commands/kb.py +0 -0
  58. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/commands/kb_metadata.py +0 -0
  59. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/commands/login.py +0 -0
  60. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/commands/prompt.py +0 -0
  61. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/commands/skills.py +0 -0
  62. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/commands/tool_credentials.py +0 -0
  63. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/commands/whoami.py +0 -0
  64. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/commands/workspace.py +0 -0
  65. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/devloop.py +0 -0
  66. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/fetch.py +0 -0
  67. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/manifest_ref.py +0 -0
  68. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/platform_client.py +0 -0
  69. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/run_debug.py +0 -0
  70. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/skills/keystone-debug/SKILL.md +0 -0
  71. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/blank/README.md.tmpl +0 -0
  72. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/blank/agent.yaml.tmpl +0 -0
  73. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/blank/env.tmpl +0 -0
  74. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/blank/gitignore.tmpl +0 -0
  75. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/blank/pkg/__init__.py.tmpl +0 -0
  76. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/blank/pkg/graph.py.tmpl +0 -0
  77. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/blank/pyproject.toml.tmpl +0 -0
  78. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/blank/tests/conftest.py.tmpl +0 -0
  79. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/blank/tests/test_graph.py.tmpl +0 -0
  80. {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
  81. {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
  82. {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
  83. {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
  84. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/guardrails/README.md.tmpl +0 -0
  85. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/guardrails/agent.yaml.tmpl +0 -0
  86. {keystone_cli-0.3.0/src/keystone_cli/templates/hitl → keystone_cli-0.4.0/src/keystone_cli/templates/guardrails}/env.tmpl +0 -0
  87. {keystone_cli-0.3.0/src/keystone_cli/templates/hitl → keystone_cli-0.4.0/src/keystone_cli/templates/guardrails}/gitignore.tmpl +0 -0
  88. {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
  89. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/guardrails/pkg/graph.py.tmpl +0 -0
  90. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/guardrails/pyproject.toml.tmpl +0 -0
  91. {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
  92. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/guardrails/tests/test_graph.py.tmpl +0 -0
  93. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/hitl/README.md.tmpl +0 -0
  94. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/hitl/agent.yaml.tmpl +0 -0
  95. {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
  96. {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
  97. {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
  98. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/hitl/pkg/graph.py.tmpl +0 -0
  99. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/hitl/pyproject.toml.tmpl +0 -0
  100. {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
  101. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/hitl/tests/test_graph.py.tmpl +0 -0
  102. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/kb-builder/README.md.tmpl +0 -0
  103. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/kb-builder/agent.yaml.tmpl +0 -0
  104. {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
  105. {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
  106. {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
  107. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/kb-builder/pkg/graph.py.tmpl +0 -0
  108. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/kb-builder/pyproject.toml.tmpl +0 -0
  109. {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
  110. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/kb-builder/tests/test_graph.py.tmpl +0 -0
  111. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/llm/README.md.tmpl +0 -0
  112. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/llm/agent.yaml.tmpl +0 -0
  113. {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
  114. {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
  115. {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
  116. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/llm/pkg/graph.py.tmpl +0 -0
  117. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/llm/pyproject.toml.tmpl +0 -0
  118. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/llm/system-prompt.txt.tmpl +0 -0
  119. {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
  120. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/llm/tests/test_graph.py.tmpl +0 -0
  121. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/llm-streaming/README.md.tmpl +0 -0
  122. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/llm-streaming/agent.yaml.tmpl +0 -0
  123. {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
  124. {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
  125. {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
  126. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/llm-streaming/pkg/graph.py.tmpl +0 -0
  127. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/llm-streaming/pyproject.toml.tmpl +0 -0
  128. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/llm-streaming/system-prompt.txt.tmpl +0 -0
  129. {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
  130. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/llm-streaming/tests/test_graph.py.tmpl +0 -0
  131. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/memory/README.md.tmpl +0 -0
  132. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/memory/agent.yaml.tmpl +0 -0
  133. {keystone_cli-0.3.0/src/keystone_cli/templates/ocr → keystone_cli-0.4.0/src/keystone_cli/templates/memory}/env.tmpl +0 -0
  134. {keystone_cli-0.3.0/src/keystone_cli/templates/ocr → keystone_cli-0.4.0/src/keystone_cli/templates/memory}/gitignore.tmpl +0 -0
  135. {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
  136. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/memory/pkg/graph.py.tmpl +0 -0
  137. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/memory/pyproject.toml.tmpl +0 -0
  138. {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
  139. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/memory/tests/test_graph.py.tmpl +0 -0
  140. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/memory-service/README.md.tmpl +0 -0
  141. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/memory-service/agent.yaml.tmpl +0 -0
  142. {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
  143. {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
  144. {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
  145. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/memory-service/pkg/graph.py.tmpl +0 -0
  146. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/memory-service/pyproject.toml.tmpl +0 -0
  147. {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
  148. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/memory-service/tests/test_graph.py.tmpl +0 -0
  149. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/ocr/README.md.tmpl +0 -0
  150. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/ocr/agent.yaml.tmpl +0 -0
  151. {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
  152. {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
  153. {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
  154. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/ocr/pkg/graph.py.tmpl +0 -0
  155. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/ocr/pyproject.toml.tmpl +0 -0
  156. {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
  157. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/ocr/tests/test_graph.py.tmpl +0 -0
  158. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/rag-qa/README.md.tmpl +0 -0
  159. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/rag-qa/agent.yaml.tmpl +0 -0
  160. {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
  161. {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
  162. {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
  163. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/rag-qa/pkg/graph.py.tmpl +0 -0
  164. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/rag-qa/pyproject.toml.tmpl +0 -0
  165. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/rag-qa/system-prompt.txt.tmpl +0 -0
  166. {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
  167. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/rag-qa/tests/test_graph.py.tmpl +0 -0
  168. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/skill/README.md.tmpl +0 -0
  169. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/skill/agent.yaml.tmpl +0 -0
  170. {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
  171. {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
  172. {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
  173. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/skill/pkg/graph.py.tmpl +0 -0
  174. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/skill/pyproject.toml.tmpl +0 -0
  175. {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
  176. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/skill/tests/test_graph.py.tmpl +0 -0
  177. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/tool-agent/README.md.tmpl +0 -0
  178. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/tool-agent/agent.yaml.tmpl +0 -0
  179. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/tool-agent/pkg/graph.py.tmpl +0 -0
  180. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/tool-agent/pyproject.toml.tmpl +0 -0
  181. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/tool-agent/system-prompt.txt.tmpl +0 -0
  182. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli/templates/tool-agent/tests/test_graph.py.tmpl +0 -0
  183. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli.egg-info/dependency_links.txt +0 -0
  184. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli.egg-info/entry_points.txt +0 -0
  185. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/src/keystone_cli.egg-info/top_level.txt +0 -0
  186. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/tests/test_agent.py +0 -0
  187. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/tests/test_agent_manifest_cmd.py +0 -0
  188. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/tests/test_agent_test_cmd.py +0 -0
  189. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/tests/test_assistant_provenance_and_flags.py +0 -0
  190. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/tests/test_auth.py +0 -0
  191. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/tests/test_build_progress.py +0 -0
  192. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/tests/test_ci_token.py +0 -0
  193. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/tests/test_config_env_mismatch.py +0 -0
  194. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/tests/test_deploy.py +0 -0
  195. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/tests/test_dev.py +0 -0
  196. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/tests/test_encoding.py +0 -0
  197. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/tests/test_fetch.py +0 -0
  198. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/tests/test_help_quality.py +0 -0
  199. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/tests/test_hitl_approver_cli.py +0 -0
  200. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/tests/test_hitl_decisions_cli.py +0 -0
  201. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/tests/test_invoke.py +0 -0
  202. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/tests/test_invoke_stream.py +0 -0
  203. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/tests/test_json_output.py +0 -0
  204. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/tests/test_jsonout.py +0 -0
  205. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/tests/test_kb_commands.py +0 -0
  206. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/tests/test_kb_metadata_commands.py +0 -0
  207. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/tests/test_login_command.py +0 -0
  208. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/tests/test_logs.py +0 -0
  209. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/tests/test_platform_client.py +0 -0
  210. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/tests/test_prompt_commands.py +0 -0
  211. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/tests/test_publish.py +0 -0
  212. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/tests/test_retire_delete.py +0 -0
  213. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/tests/test_run_debug.py +0 -0
  214. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/tests/test_runs.py +0 -0
  215. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/tests/test_skills.py +0 -0
  216. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/tests/test_status.py +0 -0
  217. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/tests/test_stdio.py +0 -0
  218. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/tests/test_template_prompt_guard.py +0 -0
  219. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/tests/test_template_unit_tests.py +0 -0
  220. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/tests/test_threads.py +0 -0
  221. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/tests/test_tls.py +0 -0
  222. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/tests/test_tool_credentials.py +0 -0
  223. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/tests/test_traces.py +0 -0
  224. {keystone_cli-0.3.0 → keystone_cli-0.4.0}/tests/test_version.py +0 -0
  225. {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.3.0"
8
- description = "Keystone pro-code agent CLI — build, test, deploy and operate agents on the Keystone platform."
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
- "keystone-agent-sdk>=0.13.10,<0.14",
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. Distributed later via an internal index (packaging task); M1 installs
38
- # from the repo path (`uv tool install ./libs/python/keystone-cli`).
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.3.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="Keystone CLI — build, test, deploy and operate pro-code agents.",
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"