stackone-ai 2.5.0__tar.gz → 2.6.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 (180) hide show
  1. stackone_ai-2.6.0/.release-please-manifest.json +3 -0
  2. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/CHANGELOG.md +14 -0
  3. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/PKG-INFO +1 -1
  4. stackone_ai-2.6.0/examples/search_tool_example.py +66 -0
  5. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/examples/semantic_search_example.py +0 -1
  6. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/examples/test_examples.py +1 -0
  7. stackone_ai-2.6.0/examples/workday_integration.py +91 -0
  8. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/pyproject.toml +1 -1
  9. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/stackone_ai/__init__.py +1 -1
  10. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/stackone_ai/models.py +2 -1
  11. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/stackone_ai/toolset.py +49 -10
  12. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/tests/test_semantic_search.py +78 -0
  13. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/uv.lock +1 -1
  14. stackone_ai-2.5.0/.release-please-manifest.json +0 -3
  15. stackone_ai-2.5.0/examples/search_tool_example.py +0 -314
  16. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/.claude/rules/development-workflow.md +0 -0
  17. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/.claude/rules/examples-standards.md +0 -0
  18. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/.claude/rules/git-workflow.md +0 -0
  19. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/.claude/rules/nix-workflow.md +0 -0
  20. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/.claude/rules/no-relative-imports.md +0 -0
  21. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/.claude/rules/package-installation.md +0 -0
  22. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/.claude/rules/release-please-standards.md +0 -0
  23. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/.claude/rules/uv-scripts.md +0 -0
  24. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/.cursor/rules/development-workflow.mdc +0 -0
  25. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/.cursor/rules/examples-standards.mdc +0 -0
  26. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/.cursor/rules/git-workflow.mdc +0 -0
  27. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/.cursor/rules/no-relative-imports.mdc +0 -0
  28. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/.cursor/rules/package-installation.mdc +0 -0
  29. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/.cursor/rules/release-please-standards.mdc +0 -0
  30. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/.cursor/rules/uv-scripts.mdc +0 -0
  31. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/.envrc +0 -0
  32. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/.github/actions/setup-nix/action.yaml +0 -0
  33. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/.github/dependabot.yaml +0 -0
  34. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/.github/workflows/ci.yaml +0 -0
  35. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/.github/workflows/nix-flake-update.yaml +0 -0
  36. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/.github/workflows/nix-flake.yaml +0 -0
  37. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/.github/workflows/release.yaml +0 -0
  38. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/.gitignore +0 -0
  39. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/.gitleaks.toml +0 -0
  40. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/.gitmodules +0 -0
  41. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/.mcp.json +0 -0
  42. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/.release-please-config.json +0 -0
  43. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/CLAUDE.md +0 -0
  44. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/LICENSE +0 -0
  45. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/README.md +0 -0
  46. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/examples/agent_tool_search.py +0 -0
  47. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/examples/crewai_integration.py +0 -0
  48. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/examples/file_uploads.py +0 -0
  49. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/examples/index.py +0 -0
  50. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/examples/langchain_integration.py +0 -0
  51. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/examples/openai_integration.py +0 -0
  52. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/examples/stackone_account_ids.py +0 -0
  53. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/flake.lock +0 -0
  54. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/flake.nix +0 -0
  55. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/justfile +0 -0
  56. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/stackone_ai/constants.py +0 -0
  57. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/stackone_ai/feedback/__init__.py +0 -0
  58. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/stackone_ai/feedback/tool.py +0 -0
  59. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/stackone_ai/integrations/__init__.py +0 -0
  60. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/stackone_ai/integrations/langgraph.py +0 -0
  61. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/stackone_ai/local_search.py +0 -0
  62. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/stackone_ai/py.typed +0 -0
  63. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/stackone_ai/semantic_search.py +0 -0
  64. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/stackone_ai/utils/__init__.py +0 -0
  65. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/stackone_ai/utils/normalize.py +0 -0
  66. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/stackone_ai/utils/tfidf_index.py +0 -0
  67. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/tests/conftest.py +0 -0
  68. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/tests/mocks/serve.ts +0 -0
  69. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/tests/test_agent_tools.py +0 -0
  70. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/tests/test_feedback.py +0 -0
  71. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/tests/test_fetch_tools.py +0 -0
  72. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/tests/test_integrations_langgraph.py +0 -0
  73. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/tests/test_local_search.py +0 -0
  74. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/tests/test_models.py +0 -0
  75. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/tests/test_tfidf_index.py +0 -0
  76. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/tests/test_tool_calling.py +0 -0
  77. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/tests/test_toolset.py +0 -0
  78. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/vendor/stackone-ai-node/.claude/rules/development-workflow.md +0 -0
  79. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/vendor/stackone-ai-node/.claude/rules/file-operations.md +0 -0
  80. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/vendor/stackone-ai-node/.claude/rules/git-workflow.md +0 -0
  81. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/vendor/stackone-ai-node/.claude/rules/pnpm-usage.md +0 -0
  82. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/vendor/stackone-ai-node/.claude/rules/typescript-patterns.md +0 -0
  83. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/vendor/stackone-ai-node/.claude/rules/typescript-testing.md +0 -0
  84. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/vendor/stackone-ai-node/.claude/skills/orama-integration/SKILL.md +0 -0
  85. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/vendor/stackone-ai-node/.cursor/rules/development-workflow.mdc +0 -0
  86. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/vendor/stackone-ai-node/.cursor/rules/file-operations.mdc +0 -0
  87. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/vendor/stackone-ai-node/.cursor/rules/git-workflow.mdc +0 -0
  88. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/vendor/stackone-ai-node/.cursor/rules/orama-integration.mdc +0 -0
  89. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/vendor/stackone-ai-node/.cursor/rules/pnpm-usage.mdc +0 -0
  90. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/vendor/stackone-ai-node/.cursor/rules/typescript-patterns.mdc +0 -0
  91. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/vendor/stackone-ai-node/.cursor/rules/typescript-testing.mdc +0 -0
  92. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/vendor/stackone-ai-node/.envrc +0 -0
  93. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/vendor/stackone-ai-node/.git +0 -0
  94. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/vendor/stackone-ai-node/.github/CODEOWNERS +0 -0
  95. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/vendor/stackone-ai-node/.github/actions/setup-nix/action.yaml +0 -0
  96. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/vendor/stackone-ai-node/.github/workflows/check-title.yaml +0 -0
  97. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/vendor/stackone-ai-node/.github/workflows/ci.yaml +0 -0
  98. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/vendor/stackone-ai-node/.github/workflows/claude.yaml +0 -0
  99. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/vendor/stackone-ai-node/.github/workflows/dry-publish.yaml +0 -0
  100. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/vendor/stackone-ai-node/.github/workflows/nix-flake.yaml +0 -0
  101. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/vendor/stackone-ai-node/.github/workflows/release.yaml +0 -0
  102. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/vendor/stackone-ai-node/.gitignore +0 -0
  103. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/vendor/stackone-ai-node/.gitleaks.toml +0 -0
  104. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/vendor/stackone-ai-node/.mcp.json +0 -0
  105. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/vendor/stackone-ai-node/.oxfmtrc.jsonc +0 -0
  106. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/vendor/stackone-ai-node/.oxlintrc.jsonc +0 -0
  107. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/vendor/stackone-ai-node/AGENTS.md +0 -0
  108. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/vendor/stackone-ai-node/CHANGELOG.md +0 -0
  109. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/vendor/stackone-ai-node/CLAUDE.md +0 -0
  110. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/vendor/stackone-ai-node/LICENSE +0 -0
  111. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/vendor/stackone-ai-node/README.md +0 -0
  112. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/vendor/stackone-ai-node/examples/README.md +0 -0
  113. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/vendor/stackone-ai-node/examples/ai-sdk-integration.test.ts +0 -0
  114. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/vendor/stackone-ai-node/examples/ai-sdk-integration.ts +0 -0
  115. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/vendor/stackone-ai-node/examples/anthropic-integration.ts +0 -0
  116. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/vendor/stackone-ai-node/examples/claude-agent-sdk-integration.test.ts +0 -0
  117. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/vendor/stackone-ai-node/examples/claude-agent-sdk-integration.ts +0 -0
  118. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/vendor/stackone-ai-node/examples/fetch-tools-debug.ts +0 -0
  119. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/vendor/stackone-ai-node/examples/fetch-tools.test.ts +0 -0
  120. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/vendor/stackone-ai-node/examples/fetch-tools.ts +0 -0
  121. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/vendor/stackone-ai-node/examples/meta-tools.ts +0 -0
  122. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/vendor/stackone-ai-node/examples/openai-integration.test.ts +0 -0
  123. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/vendor/stackone-ai-node/examples/openai-integration.ts +0 -0
  124. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/vendor/stackone-ai-node/examples/openai-responses-integration.test.ts +0 -0
  125. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/vendor/stackone-ai-node/examples/openai-responses-integration.ts +0 -0
  126. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/vendor/stackone-ai-node/examples/package.json +0 -0
  127. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/vendor/stackone-ai-node/examples/tanstack-ai-integration.test.ts +0 -0
  128. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/vendor/stackone-ai-node/examples/tanstack-ai-integration.ts +0 -0
  129. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/vendor/stackone-ai-node/examples/tsconfig.json +0 -0
  130. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/vendor/stackone-ai-node/flake.lock +0 -0
  131. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/vendor/stackone-ai-node/flake.nix +0 -0
  132. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/vendor/stackone-ai-node/knip.config.ts +0 -0
  133. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/vendor/stackone-ai-node/lefthook.yaml +0 -0
  134. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/vendor/stackone-ai-node/mocks/handlers.example-api.ts +0 -0
  135. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/vendor/stackone-ai-node/mocks/handlers.mcp.ts +0 -0
  136. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/vendor/stackone-ai-node/mocks/handlers.openai.ts +0 -0
  137. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/vendor/stackone-ai-node/mocks/handlers.stackone-ai.ts +0 -0
  138. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/vendor/stackone-ai-node/mocks/handlers.stackone-rpc.ts +0 -0
  139. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/vendor/stackone-ai-node/mocks/handlers.ts +0 -0
  140. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/vendor/stackone-ai-node/mocks/handlers.utils.ts +0 -0
  141. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/vendor/stackone-ai-node/mocks/mcp-server.ts +0 -0
  142. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/vendor/stackone-ai-node/mocks/node.ts +0 -0
  143. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/vendor/stackone-ai-node/package.json +0 -0
  144. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/vendor/stackone-ai-node/pnpm-lock.yaml +0 -0
  145. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/vendor/stackone-ai-node/pnpm-workspace.yaml +0 -0
  146. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/vendor/stackone-ai-node/src/consts.ts +0 -0
  147. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/vendor/stackone-ai-node/src/feedback.test.ts +0 -0
  148. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/vendor/stackone-ai-node/src/feedback.ts +0 -0
  149. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/vendor/stackone-ai-node/src/headers.test.ts +0 -0
  150. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/vendor/stackone-ai-node/src/headers.ts +0 -0
  151. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/vendor/stackone-ai-node/src/index.ts +0 -0
  152. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/vendor/stackone-ai-node/src/mcp-client.test.ts +0 -0
  153. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/vendor/stackone-ai-node/src/mcp-client.ts +0 -0
  154. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/vendor/stackone-ai-node/src/requestBuilder.test.ts +0 -0
  155. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/vendor/stackone-ai-node/src/requestBuilder.ts +0 -0
  156. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/vendor/stackone-ai-node/src/rpc-client.test.ts +0 -0
  157. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/vendor/stackone-ai-node/src/rpc-client.ts +0 -0
  158. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/vendor/stackone-ai-node/src/schema.ts +0 -0
  159. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/vendor/stackone-ai-node/src/tool.test-d.ts +0 -0
  160. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/vendor/stackone-ai-node/src/tool.test.ts +0 -0
  161. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/vendor/stackone-ai-node/src/tool.ts +0 -0
  162. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/vendor/stackone-ai-node/src/toolsets.test-d.ts +0 -0
  163. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/vendor/stackone-ai-node/src/toolsets.test.ts +0 -0
  164. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/vendor/stackone-ai-node/src/toolsets.ts +0 -0
  165. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/vendor/stackone-ai-node/src/types.ts +0 -0
  166. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/vendor/stackone-ai-node/src/utils/array.test.ts +0 -0
  167. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/vendor/stackone-ai-node/src/utils/array.ts +0 -0
  168. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/vendor/stackone-ai-node/src/utils/error-stackone-api.test.ts +0 -0
  169. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/vendor/stackone-ai-node/src/utils/error-stackone-api.ts +0 -0
  170. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/vendor/stackone-ai-node/src/utils/error-stackone.test.ts +0 -0
  171. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/vendor/stackone-ai-node/src/utils/error-stackone.ts +0 -0
  172. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/vendor/stackone-ai-node/src/utils/tfidf-index.test.ts +0 -0
  173. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/vendor/stackone-ai-node/src/utils/tfidf-index.ts +0 -0
  174. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/vendor/stackone-ai-node/src/utils/try-import.test.ts +0 -0
  175. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/vendor/stackone-ai-node/src/utils/try-import.ts +0 -0
  176. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/vendor/stackone-ai-node/src/utils/type.ts +0 -0
  177. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/vendor/stackone-ai-node/tsconfig.json +0 -0
  178. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/vendor/stackone-ai-node/tsdown.config.ts +0 -0
  179. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/vendor/stackone-ai-node/vitest.config.ts +0 -0
  180. {stackone_ai-2.5.0 → stackone_ai-2.6.0}/vendor/stackone-ai-node/vitest.setup.ts +0 -0
@@ -0,0 +1,3 @@
1
+ {
2
+ ".": "2.6.0"
3
+ }
@@ -1,5 +1,19 @@
1
1
  # Changelog
2
2
 
3
+ ## [2.6.0](https://github.com/StackOneHQ/stackone-ai-python/compare/stackone-ai-v2.5.1...stackone-ai-v2.6.0) (2026-04-07)
4
+
5
+
6
+ ### Features
7
+
8
+ * include available connectors in search/execute tool descriptions ([#165](https://github.com/StackOneHQ/stackone-ai-python/issues/165)) ([544f41e](https://github.com/StackOneHQ/stackone-ai-python/commit/544f41ef1340d11f58be1a34e627aa8e81f1102d))
9
+
10
+ ## [2.5.1](https://github.com/StackOneHQ/stackone-ai-python/compare/stackone-ai-v2.5.0...stackone-ai-v2.5.1) (2026-03-26)
11
+
12
+
13
+ ### Bug Fixes
14
+
15
+ * **search:** fall back to local search when semantic results don't match MCP tools ([#159](https://github.com/StackOneHQ/stackone-ai-python/issues/159)) ([2c86475](https://github.com/StackOneHQ/stackone-ai-python/commit/2c864759f43dc701d1bfa8407badf4a10f608332))
16
+
3
17
  ## [2.5.0](https://github.com/StackOneHQ/stackone-ai-python/compare/stackone-ai-v2.4.0...stackone-ai-v2.5.0) (2026-03-25)
4
18
 
5
19
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: stackone-ai
3
- Version: 2.5.0
3
+ Version: 2.6.0
4
4
  Summary: agents performing actions on your SaaS
5
5
  Author-email: StackOne <support@stackone.com>
6
6
  License-File: LICENSE
@@ -0,0 +1,66 @@
1
+ """Search tool patterns: callable wrapper and config overrides.
2
+
3
+ For semantic search basics, see semantic_search_example.py.
4
+ For full agent execution, see agent_tool_search.py.
5
+
6
+ Prerequisites:
7
+ - STACKONE_API_KEY environment variable
8
+ - STACKONE_ACCOUNT_ID environment variable
9
+
10
+ Run with:
11
+ uv run python examples/search_tool_example.py
12
+ """
13
+
14
+ from __future__ import annotations
15
+
16
+ import os
17
+
18
+ try:
19
+ from dotenv import load_dotenv
20
+
21
+ load_dotenv()
22
+ except ModuleNotFoundError:
23
+ pass
24
+
25
+ from stackone_ai import StackOneToolSet
26
+
27
+
28
+ def main() -> None:
29
+ api_key = os.getenv("STACKONE_API_KEY")
30
+ account_id = os.getenv("STACKONE_ACCOUNT_ID")
31
+
32
+ if not api_key:
33
+ print("Set STACKONE_API_KEY to run this example.")
34
+ return
35
+ if not account_id:
36
+ print("Set STACKONE_ACCOUNT_ID to run this example.")
37
+ return
38
+
39
+ # --- Example 1: get_search_tool() callable ---
40
+ print("=== get_search_tool() callable ===\n")
41
+
42
+ toolset = StackOneToolSet(api_key=api_key, account_id=account_id, search={})
43
+ search_tool = toolset.get_search_tool()
44
+
45
+ queries = ["cancel an event", "list employees", "send a message"]
46
+ for query in queries:
47
+ tools = search_tool(query, top_k=3)
48
+ names = [t.name for t in tools]
49
+ print(f' "{query}" -> {", ".join(names) or "(none)"}')
50
+
51
+ # --- Example 2: Constructor top_k vs per-call override ---
52
+ print("\n=== Constructor top_k vs per-call override ===\n")
53
+
54
+ toolset_3 = StackOneToolSet(api_key=api_key, account_id=account_id, search={"top_k": 3})
55
+
56
+ query = "manage employee records"
57
+
58
+ tools_3 = toolset_3.search_tools(query)
59
+ print(f"Constructor top_k=3: got {len(tools_3)} tools")
60
+
61
+ tools_override = toolset_3.search_tools(query, top_k=10)
62
+ print(f"Per-call top_k=10 (overrides constructor 3): got {len(tools_override)} tools")
63
+
64
+
65
+ if __name__ == "__main__":
66
+ main()
@@ -133,7 +133,6 @@ def example_search_action_names():
133
133
  print(f"Top {len(results_limited)} matches from the full catalog:")
134
134
  for r in results_limited:
135
135
  print(f" [{r.similarity_score:.2f}] {r.id}")
136
- print(f" {r.description}")
137
136
  print()
138
137
 
139
138
  # Show filtering effect when account_ids are available
@@ -33,6 +33,7 @@ OPTIONAL_DEPENDENCIES = {
33
33
  "search_tool_example.py": ["mcp"],
34
34
  "semantic_search_example.py": ["mcp"],
35
35
  "mcp_server.py": ["mcp"],
36
+ "workday_integration.py": ["openai", "mcp"],
36
37
  }
37
38
 
38
39
 
@@ -0,0 +1,91 @@
1
+ """Workday integration: timeout and account scoping for slow providers.
2
+
3
+ Workday can take 10-15s to respond. This example shows how to configure
4
+ timeout and account_ids through the execute config.
5
+
6
+ Prerequisites:
7
+ - STACKONE_API_KEY environment variable
8
+ - STACKONE_ACCOUNT_ID environment variable (a Workday-connected account)
9
+ - OPENAI_API_KEY environment variable
10
+
11
+ Run with:
12
+ uv run python examples/workday_integration.py
13
+ """
14
+
15
+ from __future__ import annotations
16
+
17
+ import json
18
+ import os
19
+
20
+ try:
21
+ from dotenv import load_dotenv
22
+
23
+ load_dotenv()
24
+ except ModuleNotFoundError:
25
+ pass
26
+
27
+ from openai import OpenAI
28
+
29
+ from stackone_ai import StackOneToolSet
30
+
31
+
32
+ def main() -> None:
33
+ api_key = os.getenv("STACKONE_API_KEY")
34
+ account_id = os.getenv("STACKONE_ACCOUNT_ID")
35
+
36
+ if not api_key:
37
+ print("Set STACKONE_API_KEY to run this example.")
38
+ return
39
+ if not account_id:
40
+ print("Set STACKONE_ACCOUNT_ID to run this example.")
41
+ return
42
+
43
+ # Timeout for slow providers, account_id for scoping
44
+ toolset = StackOneToolSet(
45
+ api_key=api_key,
46
+ account_id=account_id,
47
+ search={"method": "auto", "top_k": 5},
48
+ timeout=120,
49
+ )
50
+ client = OpenAI()
51
+
52
+ def run_agent(messages: list[dict], tools: list[dict], max_steps: int = 10) -> None:
53
+ """Simple agent loop: call LLM, execute tools, repeat."""
54
+ for _ in range(max_steps):
55
+ response = client.chat.completions.create(model="gpt-5.4", messages=messages, tools=tools)
56
+ choice = response.choices[0]
57
+
58
+ if not choice.message.tool_calls:
59
+ print(f"Answer: {choice.message.content}")
60
+ return
61
+
62
+ messages.append(choice.message.model_dump(exclude_none=True))
63
+ for tc in choice.message.tool_calls:
64
+ print(f" -> {tc.function.name}({tc.function.arguments[:80]})")
65
+ result = toolset.execute(tc.function.name, tc.function.arguments)
66
+ messages.append({"role": "tool", "tool_call_id": tc.id, "content": json.dumps(result)})
67
+
68
+ # --- Example 1: Search and execute mode ---
69
+ print("=== Search and execute mode ===\n")
70
+ run_agent(
71
+ messages=[
72
+ {"role": "system", "content": "Use tool_search to find tools, then tool_execute to run them."},
73
+ {"role": "user", "content": "List the first 5 employees."},
74
+ ],
75
+ tools=toolset.openai(mode="search_and_execute"),
76
+ )
77
+
78
+ # --- Example 2: Normal mode ---
79
+ print("\n=== Normal mode ===\n")
80
+ tools = toolset.fetch_tools(actions=["workday_*_employee*"])
81
+ if len(tools) == 0:
82
+ print("No Workday tools found for this account.")
83
+ else:
84
+ run_agent(
85
+ messages=[{"role": "user", "content": "List the first 5 employees."}],
86
+ tools=tools.to_openai(),
87
+ )
88
+
89
+
90
+ if __name__ == "__main__":
91
+ main()
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "stackone-ai"
3
- version = "2.5.0"
3
+ version = "2.6.0"
4
4
  description = "agents performing actions on your SaaS"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.10"
@@ -23,4 +23,4 @@ __all__ = [
23
23
  "SemanticSearchResponse",
24
24
  "SemanticSearchError",
25
25
  ]
26
- __version__ = "2.5.0"
26
+ __version__ = "2.6.0"
@@ -65,6 +65,7 @@ class ExecuteConfig(BaseModel):
65
65
  parameter_locations: dict[str, ParameterLocation] = Field(
66
66
  default_factory=dict, description="Maps parameter names to their location in the request"
67
67
  )
68
+ timeout: float = Field(default=60.0, description="Request timeout in seconds")
68
69
 
69
70
 
70
71
  class ToolParameters(BaseModel):
@@ -249,7 +250,7 @@ class StackOneTool(BaseModel):
249
250
  if query_params:
250
251
  request_kwargs["params"] = query_params
251
252
 
252
- response = httpx.request(**request_kwargs)
253
+ response = httpx.request(**request_kwargs, timeout=self._execute_config.timeout)
253
254
  response_status = response.status_code
254
255
  response.raise_for_status()
255
256
 
@@ -59,7 +59,7 @@ class SearchConfig(TypedDict, total=False):
59
59
  class ExecuteToolsConfig(TypedDict, total=False):
60
60
  """Execution configuration for the StackOneToolSet constructor.
61
61
 
62
- Controls default account scoping for tool execution.
62
+ Controls default account scoping and timeout for tool execution.
63
63
 
64
64
  When set to ``None`` (default), no account scoping is applied.
65
65
  When provided, ``account_ids`` flow through to ``openai(mode="search_and_execute")``
@@ -69,6 +69,10 @@ class ExecuteToolsConfig(TypedDict, total=False):
69
69
  account_ids: list[str]
70
70
  """Account IDs to scope tool discovery and execution."""
71
71
 
72
+ timeout: float
73
+ """Request timeout in seconds. Default: 60. Can also be set as a top-level
74
+ constructor param which takes precedence."""
75
+
72
76
 
73
77
  _SEARCH_DEFAULT: SearchConfig = {"method": "auto"}
74
78
 
@@ -205,13 +209,14 @@ class _ExecuteTool(StackOneTool):
205
209
  return {"error": f"Invalid input: {exc}", "tool_name": tool_name}
206
210
 
207
211
 
208
- def _create_search_tool(api_key: str) -> _SearchTool:
212
+ def _create_search_tool(api_key: str, connectors: str = "") -> _SearchTool:
209
213
  name = "tool_search"
214
+ connector_line = f" Available connectors: {connectors}." if connectors else ""
210
215
  description = (
211
216
  "Search for available tools by describing what you need. "
212
217
  "Returns matching tool names, descriptions, and parameter schemas. "
213
218
  "Use the returned parameter schemas to know exactly what to pass "
214
- "when calling tool_execute."
219
+ f"when calling tool_execute.{connector_line}"
215
220
  )
216
221
  parameters = ToolParameters(
217
222
  type="object",
@@ -259,14 +264,14 @@ def _create_search_tool(api_key: str) -> _SearchTool:
259
264
  return tool
260
265
 
261
266
 
262
- def _create_execute_tool(api_key: str) -> _ExecuteTool:
267
+ def _create_execute_tool(api_key: str, connectors: str = "") -> _ExecuteTool:
263
268
  name = "tool_execute"
269
+ connector_line = f" Available connectors: {connectors}." if connectors else ""
264
270
  description = (
265
271
  "Execute a tool by name with the given parameters. "
266
272
  "Use tool_search first to find available tools. "
267
273
  "The parameters field must match the parameter schema returned "
268
- "by tool_search. Pass parameters as a nested object matching "
269
- "the schema structure."
274
+ f"by tool_search. Pass parameters as a nested object matching the schema structure.{connector_line}"
270
275
  )
271
276
  parameters = ToolParameters(
272
277
  type="object",
@@ -415,6 +420,7 @@ class _StackOneRpcTool(StackOneTool):
415
420
  api_key: str,
416
421
  base_url: str,
417
422
  account_id: str | None,
423
+ timeout: float = 60.0,
418
424
  ) -> None:
419
425
  execute_config = ExecuteConfig(
420
426
  method="POST",
@@ -423,6 +429,7 @@ class _StackOneRpcTool(StackOneTool):
423
429
  headers={},
424
430
  body_type="json",
425
431
  parameter_locations=dict(_RPC_PARAMETER_LOCATIONS),
432
+ timeout=timeout,
426
433
  )
427
434
  super().__init__(
428
435
  description=description,
@@ -555,6 +562,7 @@ class StackOneToolSet:
555
562
  base_url: str | None = None,
556
563
  search: SearchConfig | None = None,
557
564
  execute: ExecuteToolsConfig | None = None,
565
+ timeout: float | None = None,
558
566
  ) -> None:
559
567
  """Initialize StackOne tools with authentication
560
568
 
@@ -570,7 +578,10 @@ class StackOneToolSet:
570
578
  Per-call options always override these defaults.
571
579
  execute: Execution configuration. Controls default account scoping
572
580
  for tool execution. Pass ``{"account_ids": ["acc-1"]}`` to scope
573
- meta tools to specific accounts.
581
+ tools to specific accounts.
582
+ timeout: Request timeout in seconds for tool execution HTTP calls.
583
+ Default: 60. Takes precedence over ``execute.timeout`` if set.
584
+ Increase for slow providers (e.g. Workday).
574
585
 
575
586
  Raises:
576
587
  ToolsetConfigError: If no API key is provided or found in environment
@@ -584,10 +595,12 @@ class StackOneToolSet:
584
595
  self.api_key: str = api_key_value
585
596
  self.account_id = account_id
586
597
  self.base_url = base_url or DEFAULT_BASE_URL
587
- self._account_ids: list[str] = []
598
+ self._account_ids: list[str] = execute.get("account_ids", []) if execute else []
588
599
  self._semantic_client: SemanticSearchClient | None = None
589
600
  self._search_config: SearchConfig | None = search
590
601
  self._execute_config: ExecuteToolsConfig | None = execute
602
+ execute_timeout = execute.get("timeout") if execute else None
603
+ self._timeout: float = timeout if timeout is not None else (execute_timeout or 60.0)
591
604
  self._tools_cache: Tools | None = None
592
605
 
593
606
  def set_accounts(self, account_ids: list[str]) -> StackOneToolSet:
@@ -645,10 +658,20 @@ class StackOneToolSet:
645
658
  if account_ids:
646
659
  self._account_ids = account_ids
647
660
 
648
- search_tool = _create_search_tool(self.api_key)
661
+ # Discover available connectors for dynamic descriptions
662
+ connectors_str = ""
663
+ try:
664
+ all_tools = self.fetch_tools(account_ids=self._account_ids)
665
+ connectors = sorted(all_tools.get_connectors())
666
+ if connectors:
667
+ connectors_str = ", ".join(connectors)
668
+ except Exception:
669
+ logger.debug("Could not discover connectors for tool descriptions")
670
+
671
+ search_tool = _create_search_tool(self.api_key, connectors=connectors_str)
649
672
  search_tool._toolset = self
650
673
 
651
- execute_tool = _create_execute_tool(self.api_key)
674
+ execute_tool = _create_execute_tool(self.api_key, connectors=connectors_str)
652
675
  execute_tool._toolset = self
653
676
 
654
677
  return Tools([search_tool, execute_tool])
@@ -933,6 +956,21 @@ class StackOneToolSet:
933
956
  matched_tools = [t for t in all_tools if t.name in seen_names]
934
957
  matched_tools.sort(key=lambda t: action_order.get(t.name, float("inf")))
935
958
 
959
+ # Auto mode: if semantic returned results but none matched MCP tools, fall back to local
960
+ if effective_search == "auto" and len(matched_tools) == 0:
961
+ logger.warning(
962
+ "Semantic search returned %d results but none matched MCP tools, "
963
+ "falling back to local search",
964
+ len(all_results),
965
+ )
966
+ return self._local_search(
967
+ query,
968
+ all_tools,
969
+ connector=connector,
970
+ top_k=effective_top_k,
971
+ min_similarity=effective_min_sim,
972
+ )
973
+
936
974
  return Tools(matched_tools)
937
975
 
938
976
  except SemanticSearchError as e:
@@ -1177,6 +1215,7 @@ class StackOneToolSet:
1177
1215
  api_key=self.api_key,
1178
1216
  base_url=self.base_url,
1179
1217
  account_id=account_id,
1218
+ timeout=self._timeout,
1180
1219
  )
1181
1220
 
1182
1221
  def _normalize_schema_properties(self, schema: dict[str, Any]) -> dict[str, Any]:
@@ -959,3 +959,81 @@ class TestSemanticSearchDeduplication:
959
959
  assert results[0].id == "breathehr_1.0.0_breathehr_list_employees_global"
960
960
  # Sorted by score descending
961
961
  assert results[0].similarity_score == 0.95
962
+
963
+
964
+ class TestZeroMatchFallback:
965
+ """Tests for fallback when semantic results don't match MCP tools."""
966
+
967
+ @patch.object(SemanticSearchClient, "search")
968
+ @patch("stackone_ai.toolset._fetch_mcp_tools")
969
+ def test_auto_mode_falls_back_when_no_tools_match(
970
+ self,
971
+ mock_fetch: MagicMock,
972
+ mock_search: MagicMock,
973
+ ) -> None:
974
+ """Auto mode falls back to local search when semantic results don't match any MCP tools."""
975
+ from stackone_ai import StackOneToolSet
976
+ from stackone_ai.toolset import _McpToolDefinition
977
+
978
+ # Semantic returns results with IDs that won't match MCP tool names
979
+ mock_search.return_value = SemanticSearchResponse(
980
+ results=[
981
+ SemanticSearchResult(
982
+ id="unknown_1.0.0_nonexistent_action_global",
983
+ similarity_score=0.95,
984
+ ),
985
+ ],
986
+ total_count=1,
987
+ query="manage employees",
988
+ )
989
+
990
+ mock_fetch.return_value = [
991
+ _McpToolDefinition(
992
+ name="bamboohr_create_employee",
993
+ description="Creates a new employee in BambooHR",
994
+ input_schema={"type": "object", "properties": {}},
995
+ ),
996
+ ]
997
+
998
+ toolset = StackOneToolSet(api_key="test-key", search={"method": "auto"})
999
+ tools = toolset.search_tools("manage employees", top_k=5)
1000
+
1001
+ # Should fall back to local search and return results (not empty)
1002
+ assert len(tools) > 0
1003
+
1004
+ @patch.object(SemanticSearchClient, "search")
1005
+ @patch("stackone_ai.toolset._fetch_mcp_tools")
1006
+ def test_semantic_mode_does_not_fall_back(
1007
+ self,
1008
+ mock_fetch: MagicMock,
1009
+ mock_search: MagicMock,
1010
+ ) -> None:
1011
+ """Semantic mode returns empty results when no tools match, does not fall back."""
1012
+ from stackone_ai import StackOneToolSet
1013
+ from stackone_ai.toolset import _McpToolDefinition
1014
+
1015
+ # Semantic returns results with IDs that won't match MCP tool names
1016
+ mock_search.return_value = SemanticSearchResponse(
1017
+ results=[
1018
+ SemanticSearchResult(
1019
+ id="unknown_1.0.0_nonexistent_action_global",
1020
+ similarity_score=0.95,
1021
+ ),
1022
+ ],
1023
+ total_count=1,
1024
+ query="manage employees",
1025
+ )
1026
+
1027
+ mock_fetch.return_value = [
1028
+ _McpToolDefinition(
1029
+ name="bamboohr_create_employee",
1030
+ description="Creates a new employee in BambooHR",
1031
+ input_schema={"type": "object", "properties": {}},
1032
+ ),
1033
+ ]
1034
+
1035
+ toolset = StackOneToolSet(api_key="test-key", search={"method": "auto"})
1036
+ tools = toolset.search_tools("manage employees", search="semantic", top_k=5)
1037
+
1038
+ # Semantic mode should return empty, not fall back
1039
+ assert len(tools) == 0
@@ -3972,7 +3972,7 @@ wheels = [
3972
3972
 
3973
3973
  [[package]]
3974
3974
  name = "stackone-ai"
3975
- version = "2.5.0"
3975
+ version = "2.6.0"
3976
3976
  source = { editable = "." }
3977
3977
  dependencies = [
3978
3978
  { name = "bm25s" },
@@ -1,3 +0,0 @@
1
- {
2
- ".": "2.5.0"
3
- }