stackone-ai 2.4.0__tar.gz → 2.5.1__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.
- stackone_ai-2.5.1/.release-please-manifest.json +3 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/CHANGELOG.md +14 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/PKG-INFO +1 -1
- stackone_ai-2.5.1/examples/agent_tool_search.py +202 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/examples/crewai_integration.py +1 -1
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/examples/langchain_integration.py +1 -1
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/examples/openai_integration.py +2 -2
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/examples/search_tool_example.py +2 -2
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/examples/semantic_search_example.py +7 -7
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/pyproject.toml +1 -1
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/stackone_ai/__init__.py +3 -2
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/stackone_ai/models.py +14 -2
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/stackone_ai/semantic_search.py +14 -22
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/stackone_ai/toolset.py +394 -27
- stackone_ai-2.5.1/tests/test_agent_tools.py +536 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/tests/test_semantic_search.py +156 -131
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/uv.lock +1 -1
- stackone_ai-2.4.0/.release-please-manifest.json +0 -3
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/.claude/rules/development-workflow.md +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/.claude/rules/examples-standards.md +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/.claude/rules/git-workflow.md +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/.claude/rules/nix-workflow.md +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/.claude/rules/no-relative-imports.md +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/.claude/rules/package-installation.md +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/.claude/rules/release-please-standards.md +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/.claude/rules/uv-scripts.md +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/.cursor/rules/development-workflow.mdc +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/.cursor/rules/examples-standards.mdc +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/.cursor/rules/git-workflow.mdc +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/.cursor/rules/no-relative-imports.mdc +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/.cursor/rules/package-installation.mdc +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/.cursor/rules/release-please-standards.mdc +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/.cursor/rules/uv-scripts.mdc +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/.envrc +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/.github/actions/setup-nix/action.yaml +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/.github/dependabot.yaml +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/.github/workflows/ci.yaml +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/.github/workflows/nix-flake-update.yaml +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/.github/workflows/nix-flake.yaml +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/.github/workflows/release.yaml +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/.gitignore +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/.gitleaks.toml +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/.gitmodules +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/.mcp.json +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/.release-please-config.json +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/CLAUDE.md +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/LICENSE +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/README.md +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/examples/file_uploads.py +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/examples/index.py +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/examples/stackone_account_ids.py +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/examples/test_examples.py +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/flake.lock +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/flake.nix +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/justfile +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/stackone_ai/constants.py +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/stackone_ai/feedback/__init__.py +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/stackone_ai/feedback/tool.py +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/stackone_ai/integrations/__init__.py +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/stackone_ai/integrations/langgraph.py +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/stackone_ai/local_search.py +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/stackone_ai/py.typed +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/stackone_ai/utils/__init__.py +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/stackone_ai/utils/normalize.py +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/stackone_ai/utils/tfidf_index.py +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/tests/conftest.py +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/tests/mocks/serve.ts +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/tests/test_feedback.py +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/tests/test_fetch_tools.py +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/tests/test_integrations_langgraph.py +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/tests/test_local_search.py +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/tests/test_models.py +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/tests/test_tfidf_index.py +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/tests/test_tool_calling.py +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/tests/test_toolset.py +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/vendor/stackone-ai-node/.claude/rules/development-workflow.md +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/vendor/stackone-ai-node/.claude/rules/file-operations.md +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/vendor/stackone-ai-node/.claude/rules/git-workflow.md +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/vendor/stackone-ai-node/.claude/rules/pnpm-usage.md +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/vendor/stackone-ai-node/.claude/rules/typescript-patterns.md +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/vendor/stackone-ai-node/.claude/rules/typescript-testing.md +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/vendor/stackone-ai-node/.claude/skills/orama-integration/SKILL.md +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/vendor/stackone-ai-node/.cursor/rules/development-workflow.mdc +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/vendor/stackone-ai-node/.cursor/rules/file-operations.mdc +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/vendor/stackone-ai-node/.cursor/rules/git-workflow.mdc +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/vendor/stackone-ai-node/.cursor/rules/orama-integration.mdc +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/vendor/stackone-ai-node/.cursor/rules/pnpm-usage.mdc +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/vendor/stackone-ai-node/.cursor/rules/typescript-patterns.mdc +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/vendor/stackone-ai-node/.cursor/rules/typescript-testing.mdc +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/vendor/stackone-ai-node/.envrc +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/vendor/stackone-ai-node/.git +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/vendor/stackone-ai-node/.github/CODEOWNERS +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/vendor/stackone-ai-node/.github/actions/setup-nix/action.yaml +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/vendor/stackone-ai-node/.github/workflows/check-title.yaml +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/vendor/stackone-ai-node/.github/workflows/ci.yaml +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/vendor/stackone-ai-node/.github/workflows/claude.yaml +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/vendor/stackone-ai-node/.github/workflows/dry-publish.yaml +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/vendor/stackone-ai-node/.github/workflows/nix-flake.yaml +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/vendor/stackone-ai-node/.github/workflows/release.yaml +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/vendor/stackone-ai-node/.gitignore +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/vendor/stackone-ai-node/.gitleaks.toml +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/vendor/stackone-ai-node/.mcp.json +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/vendor/stackone-ai-node/.oxfmtrc.jsonc +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/vendor/stackone-ai-node/.oxlintrc.jsonc +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/vendor/stackone-ai-node/AGENTS.md +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/vendor/stackone-ai-node/CHANGELOG.md +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/vendor/stackone-ai-node/CLAUDE.md +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/vendor/stackone-ai-node/LICENSE +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/vendor/stackone-ai-node/README.md +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/vendor/stackone-ai-node/examples/README.md +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/vendor/stackone-ai-node/examples/ai-sdk-integration.test.ts +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/vendor/stackone-ai-node/examples/ai-sdk-integration.ts +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/vendor/stackone-ai-node/examples/anthropic-integration.ts +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/vendor/stackone-ai-node/examples/claude-agent-sdk-integration.test.ts +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/vendor/stackone-ai-node/examples/claude-agent-sdk-integration.ts +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/vendor/stackone-ai-node/examples/fetch-tools-debug.ts +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/vendor/stackone-ai-node/examples/fetch-tools.test.ts +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/vendor/stackone-ai-node/examples/fetch-tools.ts +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/vendor/stackone-ai-node/examples/meta-tools.ts +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/vendor/stackone-ai-node/examples/openai-integration.test.ts +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/vendor/stackone-ai-node/examples/openai-integration.ts +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/vendor/stackone-ai-node/examples/openai-responses-integration.test.ts +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/vendor/stackone-ai-node/examples/openai-responses-integration.ts +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/vendor/stackone-ai-node/examples/package.json +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/vendor/stackone-ai-node/examples/tanstack-ai-integration.test.ts +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/vendor/stackone-ai-node/examples/tanstack-ai-integration.ts +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/vendor/stackone-ai-node/examples/tsconfig.json +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/vendor/stackone-ai-node/flake.lock +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/vendor/stackone-ai-node/flake.nix +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/vendor/stackone-ai-node/knip.config.ts +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/vendor/stackone-ai-node/lefthook.yaml +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/vendor/stackone-ai-node/mocks/handlers.example-api.ts +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/vendor/stackone-ai-node/mocks/handlers.mcp.ts +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/vendor/stackone-ai-node/mocks/handlers.openai.ts +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/vendor/stackone-ai-node/mocks/handlers.stackone-ai.ts +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/vendor/stackone-ai-node/mocks/handlers.stackone-rpc.ts +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/vendor/stackone-ai-node/mocks/handlers.ts +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/vendor/stackone-ai-node/mocks/handlers.utils.ts +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/vendor/stackone-ai-node/mocks/mcp-server.ts +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/vendor/stackone-ai-node/mocks/node.ts +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/vendor/stackone-ai-node/package.json +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/vendor/stackone-ai-node/pnpm-lock.yaml +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/vendor/stackone-ai-node/pnpm-workspace.yaml +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/vendor/stackone-ai-node/src/consts.ts +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/vendor/stackone-ai-node/src/feedback.test.ts +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/vendor/stackone-ai-node/src/feedback.ts +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/vendor/stackone-ai-node/src/headers.test.ts +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/vendor/stackone-ai-node/src/headers.ts +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/vendor/stackone-ai-node/src/index.ts +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/vendor/stackone-ai-node/src/mcp-client.test.ts +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/vendor/stackone-ai-node/src/mcp-client.ts +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/vendor/stackone-ai-node/src/requestBuilder.test.ts +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/vendor/stackone-ai-node/src/requestBuilder.ts +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/vendor/stackone-ai-node/src/rpc-client.test.ts +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/vendor/stackone-ai-node/src/rpc-client.ts +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/vendor/stackone-ai-node/src/schema.ts +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/vendor/stackone-ai-node/src/tool.test-d.ts +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/vendor/stackone-ai-node/src/tool.test.ts +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/vendor/stackone-ai-node/src/tool.ts +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/vendor/stackone-ai-node/src/toolsets.test-d.ts +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/vendor/stackone-ai-node/src/toolsets.test.ts +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/vendor/stackone-ai-node/src/toolsets.ts +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/vendor/stackone-ai-node/src/types.ts +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/vendor/stackone-ai-node/src/utils/array.test.ts +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/vendor/stackone-ai-node/src/utils/array.ts +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/vendor/stackone-ai-node/src/utils/error-stackone-api.test.ts +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/vendor/stackone-ai-node/src/utils/error-stackone-api.ts +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/vendor/stackone-ai-node/src/utils/error-stackone.test.ts +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/vendor/stackone-ai-node/src/utils/error-stackone.ts +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/vendor/stackone-ai-node/src/utils/tfidf-index.test.ts +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/vendor/stackone-ai-node/src/utils/tfidf-index.ts +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/vendor/stackone-ai-node/src/utils/try-import.test.ts +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/vendor/stackone-ai-node/src/utils/try-import.ts +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/vendor/stackone-ai-node/src/utils/type.ts +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/vendor/stackone-ai-node/tsconfig.json +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/vendor/stackone-ai-node/tsdown.config.ts +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/vendor/stackone-ai-node/vitest.config.ts +0 -0
- {stackone_ai-2.4.0 → stackone_ai-2.5.1}/vendor/stackone-ai-node/vitest.setup.ts +0 -0
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [2.5.1](https://github.com/StackOneHQ/stackone-ai-python/compare/stackone-ai-v2.5.0...stackone-ai-v2.5.1) (2026-03-26)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Bug Fixes
|
|
7
|
+
|
|
8
|
+
* **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))
|
|
9
|
+
|
|
10
|
+
## [2.5.0](https://github.com/StackOneHQ/stackone-ai-python/compare/stackone-ai-v2.4.0...stackone-ai-v2.5.0) (2026-03-25)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
### Features
|
|
14
|
+
|
|
15
|
+
* **search-tools:** LLM-driven search and execute and new API ([#151](https://github.com/StackOneHQ/stackone-ai-python/issues/151)) ([a5e5723](https://github.com/StackOneHQ/stackone-ai-python/commit/a5e5723689d702ce4d176194a0d6a43486bcdff7))
|
|
16
|
+
|
|
3
17
|
## [2.4.0](https://github.com/StackOneHQ/stackone-ai-python/compare/stackone-ai-v2.3.1...stackone-ai-v2.4.0) (2026-03-06)
|
|
4
18
|
|
|
5
19
|
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
"""Search and execute example: LLM-driven tool discovery and execution.
|
|
2
|
+
|
|
3
|
+
There are two ways to give tools to an LLM:
|
|
4
|
+
|
|
5
|
+
1. ``toolset.openai()`` — fetches ALL tools and converts them to OpenAI format.
|
|
6
|
+
Token cost scales with the number of tools in your catalog.
|
|
7
|
+
|
|
8
|
+
2. ``toolset.openai(mode="search_and_execute")`` — returns just 2 tools
|
|
9
|
+
(tool_search + tool_execute). The LLM discovers and runs tools on-demand,
|
|
10
|
+
keeping token usage constant regardless of catalog size.
|
|
11
|
+
|
|
12
|
+
This example demonstrates approach 2 with two patterns:
|
|
13
|
+
- Raw client (OpenAI): manual agent loop with ``toolset.execute()``
|
|
14
|
+
- LangChain: framework handles tool execution automatically
|
|
15
|
+
|
|
16
|
+
Prerequisites:
|
|
17
|
+
- STACKONE_API_KEY environment variable
|
|
18
|
+
- STACKONE_ACCOUNT_ID environment variable
|
|
19
|
+
- OPENAI_API_KEY environment variable
|
|
20
|
+
|
|
21
|
+
Run with:
|
|
22
|
+
uv run python examples/agent_tool_search.py
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
from __future__ import annotations
|
|
26
|
+
|
|
27
|
+
import json
|
|
28
|
+
import os
|
|
29
|
+
|
|
30
|
+
try:
|
|
31
|
+
from dotenv import load_dotenv
|
|
32
|
+
|
|
33
|
+
load_dotenv()
|
|
34
|
+
except ModuleNotFoundError:
|
|
35
|
+
pass
|
|
36
|
+
|
|
37
|
+
from stackone_ai import StackOneToolSet
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def example_openai() -> None:
|
|
41
|
+
"""Raw client: OpenAI.
|
|
42
|
+
|
|
43
|
+
Shows: init toolset -> get OpenAI tools -> manual agent loop with toolset.execute().
|
|
44
|
+
"""
|
|
45
|
+
print("=" * 60)
|
|
46
|
+
print("Example 1: Raw client (OpenAI) — manual execution")
|
|
47
|
+
print("=" * 60)
|
|
48
|
+
print()
|
|
49
|
+
|
|
50
|
+
try:
|
|
51
|
+
from openai import OpenAI
|
|
52
|
+
except ImportError:
|
|
53
|
+
print("Skipped: pip install openai")
|
|
54
|
+
print()
|
|
55
|
+
return
|
|
56
|
+
|
|
57
|
+
if not os.getenv("OPENAI_API_KEY"):
|
|
58
|
+
print("Skipped: Set OPENAI_API_KEY to run this example.")
|
|
59
|
+
print()
|
|
60
|
+
return
|
|
61
|
+
|
|
62
|
+
# 1. Init toolset
|
|
63
|
+
account_id = os.getenv("STACKONE_ACCOUNT_ID")
|
|
64
|
+
toolset = StackOneToolSet(
|
|
65
|
+
account_id=account_id,
|
|
66
|
+
search={"method": "semantic", "top_k": 3},
|
|
67
|
+
execute={"account_ids": [account_id]} if account_id else None,
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
# 2. Get tools in OpenAI format
|
|
71
|
+
openai_tools = toolset.openai(mode="search_and_execute")
|
|
72
|
+
|
|
73
|
+
# 3. Create OpenAI client and run agent loop
|
|
74
|
+
client = OpenAI()
|
|
75
|
+
messages: list[dict] = [
|
|
76
|
+
{
|
|
77
|
+
"role": "system",
|
|
78
|
+
"content": (
|
|
79
|
+
"You are a helpful scheduling assistant. Use tool_search to find relevant tools, "
|
|
80
|
+
"then tool_execute to run them. Always read the parameter schemas from tool_search "
|
|
81
|
+
"results carefully. If a tool needs a user URI, first search for and call a "
|
|
82
|
+
'"get current user" tool to obtain it. If a tool execution fails, try different '
|
|
83
|
+
"parameters or a different tool."
|
|
84
|
+
),
|
|
85
|
+
},
|
|
86
|
+
{"role": "user", "content": "List my upcoming Calendly events for the next week."},
|
|
87
|
+
]
|
|
88
|
+
|
|
89
|
+
for _step in range(10):
|
|
90
|
+
response = client.chat.completions.create(
|
|
91
|
+
model="gpt-5.4",
|
|
92
|
+
messages=messages,
|
|
93
|
+
tools=openai_tools,
|
|
94
|
+
tool_choice="auto",
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
choice = response.choices[0]
|
|
98
|
+
|
|
99
|
+
# 4. If no tool calls, print final answer and stop
|
|
100
|
+
if not choice.message.tool_calls:
|
|
101
|
+
print(f"Answer: {choice.message.content}")
|
|
102
|
+
break
|
|
103
|
+
|
|
104
|
+
# 5. Execute tool calls manually and feed results back
|
|
105
|
+
messages.append(choice.message.model_dump(exclude_none=True))
|
|
106
|
+
for tool_call in choice.message.tool_calls:
|
|
107
|
+
print(f" -> {tool_call.function.name}({tool_call.function.arguments})")
|
|
108
|
+
result = toolset.execute(tool_call.function.name, tool_call.function.arguments)
|
|
109
|
+
messages.append(
|
|
110
|
+
{
|
|
111
|
+
"role": "tool",
|
|
112
|
+
"tool_call_id": tool_call.id,
|
|
113
|
+
"content": json.dumps(result),
|
|
114
|
+
}
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
print()
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
def example_langchain() -> None:
|
|
121
|
+
"""Framework: LangChain with auto-execution.
|
|
122
|
+
|
|
123
|
+
Shows: init toolset -> get LangChain tools -> bind to model -> framework executes tools.
|
|
124
|
+
No toolset.execute() needed — the framework calls _run() on tools automatically.
|
|
125
|
+
"""
|
|
126
|
+
print("=" * 60)
|
|
127
|
+
print("Example 2: LangChain — framework handles execution")
|
|
128
|
+
print("=" * 60)
|
|
129
|
+
print()
|
|
130
|
+
|
|
131
|
+
try:
|
|
132
|
+
from langchain_core.messages import AIMessage, HumanMessage, SystemMessage, ToolMessage
|
|
133
|
+
from langchain_openai import ChatOpenAI
|
|
134
|
+
except ImportError:
|
|
135
|
+
print("Skipped: pip install langchain-openai")
|
|
136
|
+
print()
|
|
137
|
+
return
|
|
138
|
+
|
|
139
|
+
if not os.getenv("OPENAI_API_KEY"):
|
|
140
|
+
print("Skipped: Set OPENAI_API_KEY to run this example.")
|
|
141
|
+
print()
|
|
142
|
+
return
|
|
143
|
+
|
|
144
|
+
# 1. Init toolset
|
|
145
|
+
account_id = os.getenv("STACKONE_ACCOUNT_ID")
|
|
146
|
+
toolset = StackOneToolSet(
|
|
147
|
+
account_id=account_id,
|
|
148
|
+
search={"method": "semantic", "top_k": 3},
|
|
149
|
+
execute={"account_ids": [account_id]} if account_id else None,
|
|
150
|
+
)
|
|
151
|
+
|
|
152
|
+
# 2. Get tools in LangChain format and bind to model
|
|
153
|
+
langchain_tools = toolset.langchain(mode="search_and_execute")
|
|
154
|
+
tools_by_name = {tool.name: tool for tool in langchain_tools}
|
|
155
|
+
model = ChatOpenAI(model="gpt-5.4").bind_tools(langchain_tools)
|
|
156
|
+
|
|
157
|
+
# 3. Run agent loop
|
|
158
|
+
messages = [
|
|
159
|
+
SystemMessage(
|
|
160
|
+
content=(
|
|
161
|
+
"You are a helpful scheduling assistant. Use tool_search to find relevant tools, "
|
|
162
|
+
"then tool_execute to run them. Always read the parameter schemas from tool_search "
|
|
163
|
+
"results carefully. If a tool needs a user URI, first search for and call a "
|
|
164
|
+
'"get current user" tool to obtain it. If a tool execution fails, try different '
|
|
165
|
+
"parameters or a different tool."
|
|
166
|
+
),
|
|
167
|
+
),
|
|
168
|
+
HumanMessage(content="List my upcoming Calendly events for the next week."),
|
|
169
|
+
]
|
|
170
|
+
|
|
171
|
+
for _step in range(10):
|
|
172
|
+
response: AIMessage = model.invoke(messages)
|
|
173
|
+
|
|
174
|
+
# 4. If no tool calls, print final answer and stop
|
|
175
|
+
if not response.tool_calls:
|
|
176
|
+
print(f"Answer: {response.content}")
|
|
177
|
+
break
|
|
178
|
+
|
|
179
|
+
# 5. Framework-compatible execution — invoke LangChain tools directly
|
|
180
|
+
messages.append(response)
|
|
181
|
+
for tool_call in response.tool_calls:
|
|
182
|
+
print(f" -> {tool_call['name']}({json.dumps(tool_call['args'])})")
|
|
183
|
+
tool = tools_by_name[tool_call["name"]]
|
|
184
|
+
result = tool.invoke(tool_call["args"])
|
|
185
|
+
messages.append(ToolMessage(content=json.dumps(result), tool_call_id=tool_call["id"]))
|
|
186
|
+
|
|
187
|
+
print()
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
def main() -> None:
|
|
191
|
+
"""Run all examples."""
|
|
192
|
+
api_key = os.getenv("STACKONE_API_KEY")
|
|
193
|
+
if not api_key:
|
|
194
|
+
print("Set STACKONE_API_KEY to run these examples.")
|
|
195
|
+
return
|
|
196
|
+
|
|
197
|
+
example_openai()
|
|
198
|
+
example_langchain()
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
if __name__ == "__main__":
|
|
202
|
+
main()
|
|
@@ -34,7 +34,7 @@ def crewai_integration():
|
|
|
34
34
|
goal=f"What is the employee with the id {employee_id}?",
|
|
35
35
|
backstory="With over 10 years of experience in HR and employee management, "
|
|
36
36
|
"you excel at finding patterns in complex datasets.",
|
|
37
|
-
llm="gpt-
|
|
37
|
+
llm="gpt-5.4",
|
|
38
38
|
tools=langchain_tools,
|
|
39
39
|
max_iter=2,
|
|
40
40
|
)
|
|
@@ -33,7 +33,7 @@ def langchain_integration() -> None:
|
|
|
33
33
|
assert hasattr(tool, "args_schema"), "Expected tool to have args_schema"
|
|
34
34
|
|
|
35
35
|
# Create model with tools
|
|
36
|
-
model = ChatOpenAI(model="gpt-
|
|
36
|
+
model = ChatOpenAI(model="gpt-5.4")
|
|
37
37
|
model_with_tools = model.bind_tools(langchain_tools)
|
|
38
38
|
|
|
39
39
|
result = model_with_tools.invoke(f"Can you get me information about employee with ID: {employee_id}?")
|
|
@@ -53,7 +53,7 @@ def openai_integration() -> None:
|
|
|
53
53
|
]
|
|
54
54
|
|
|
55
55
|
response = client.chat.completions.create(
|
|
56
|
-
model="gpt-
|
|
56
|
+
model="gpt-5.4",
|
|
57
57
|
messages=messages,
|
|
58
58
|
tools=openai_tools,
|
|
59
59
|
tool_choice="auto",
|
|
@@ -81,7 +81,7 @@ def openai_integration() -> None:
|
|
|
81
81
|
|
|
82
82
|
# Verify the final response
|
|
83
83
|
final_response = client.chat.completions.create(
|
|
84
|
-
model="gpt-
|
|
84
|
+
model="gpt-5.4",
|
|
85
85
|
messages=messages,
|
|
86
86
|
tools=openai_tools,
|
|
87
87
|
tool_choice="auto",
|
|
@@ -198,7 +198,7 @@ def example_with_openai():
|
|
|
198
198
|
|
|
199
199
|
# Create a chat completion with discovered tools
|
|
200
200
|
response = client.chat.completions.create(
|
|
201
|
-
model="gpt-4",
|
|
201
|
+
model="gpt-5.4",
|
|
202
202
|
messages=[
|
|
203
203
|
{
|
|
204
204
|
"role": "system",
|
|
@@ -246,7 +246,7 @@ def example_with_langchain():
|
|
|
246
246
|
print(f" - {tool.name}: {tool.description}")
|
|
247
247
|
|
|
248
248
|
# Create LangChain agent
|
|
249
|
-
llm = ChatOpenAI(model="gpt-4", temperature=0)
|
|
249
|
+
llm = ChatOpenAI(model="gpt-5.4", temperature=0)
|
|
250
250
|
|
|
251
251
|
prompt = ChatPromptTemplate.from_messages(
|
|
252
252
|
[
|
|
@@ -132,7 +132,7 @@ def example_search_action_names():
|
|
|
132
132
|
# Show the limited results
|
|
133
133
|
print(f"Top {len(results_limited)} matches from the full catalog:")
|
|
134
134
|
for r in results_limited:
|
|
135
|
-
print(f" [{r.similarity_score:.2f}] {r.
|
|
135
|
+
print(f" [{r.similarity_score:.2f}] {r.id}")
|
|
136
136
|
print(f" {r.description}")
|
|
137
137
|
print()
|
|
138
138
|
|
|
@@ -143,7 +143,7 @@ def example_search_action_names():
|
|
|
143
143
|
filtered = toolset.search_action_names(query, account_ids=_account_ids, top_k=5)
|
|
144
144
|
print(f" Filtered to {len(filtered)} matches (only your connectors):")
|
|
145
145
|
for r in filtered:
|
|
146
|
-
print(f" [{r.similarity_score:.2f}] {r.
|
|
146
|
+
print(f" [{r.similarity_score:.2f}] {r.id}")
|
|
147
147
|
else:
|
|
148
148
|
print("Tip: Set STACKONE_ACCOUNT_ID to see results filtered to your linked connectors.")
|
|
149
149
|
|
|
@@ -197,7 +197,7 @@ def example_search_tools_with_connector():
|
|
|
197
197
|
print("=" * 60)
|
|
198
198
|
print()
|
|
199
199
|
|
|
200
|
-
toolset = StackOneToolSet()
|
|
200
|
+
toolset = StackOneToolSet(search={})
|
|
201
201
|
|
|
202
202
|
query = "book a meeting"
|
|
203
203
|
connector = "calendly"
|
|
@@ -230,7 +230,7 @@ def example_search_tool_agent_loop():
|
|
|
230
230
|
print("=" * 60)
|
|
231
231
|
print()
|
|
232
232
|
|
|
233
|
-
toolset = StackOneToolSet()
|
|
233
|
+
toolset = StackOneToolSet(search={})
|
|
234
234
|
|
|
235
235
|
print("Step 1: Fetching tools from your linked accounts via MCP...")
|
|
236
236
|
all_tools = toolset.fetch_tools(account_ids=_account_ids)
|
|
@@ -281,7 +281,7 @@ def example_openai_agent_loop():
|
|
|
281
281
|
|
|
282
282
|
if openai_key:
|
|
283
283
|
client = OpenAI()
|
|
284
|
-
model = "gpt-
|
|
284
|
+
model = "gpt-5.4"
|
|
285
285
|
provider = "OpenAI"
|
|
286
286
|
elif google_key:
|
|
287
287
|
client = OpenAI(
|
|
@@ -298,7 +298,7 @@ def example_openai_agent_loop():
|
|
|
298
298
|
print(f"Using {provider} ({model})")
|
|
299
299
|
print()
|
|
300
300
|
|
|
301
|
-
toolset = StackOneToolSet()
|
|
301
|
+
toolset = StackOneToolSet(search={})
|
|
302
302
|
|
|
303
303
|
query = "list upcoming events"
|
|
304
304
|
print(f'Step 1: Discovering tools for "{query}" via semantic search...')
|
|
@@ -358,7 +358,7 @@ def example_langchain_semantic():
|
|
|
358
358
|
print()
|
|
359
359
|
return
|
|
360
360
|
|
|
361
|
-
toolset = StackOneToolSet()
|
|
361
|
+
toolset = StackOneToolSet(search={})
|
|
362
362
|
|
|
363
363
|
query = "remove a user from the team"
|
|
364
364
|
print(f'Step 1: Searching for "{query}" via semantic search...')
|
|
@@ -7,12 +7,13 @@ from stackone_ai.semantic_search import (
|
|
|
7
7
|
SemanticSearchResponse,
|
|
8
8
|
SemanticSearchResult,
|
|
9
9
|
)
|
|
10
|
-
from stackone_ai.toolset import SearchConfig, SearchMode, SearchTool, StackOneToolSet
|
|
10
|
+
from stackone_ai.toolset import ExecuteToolsConfig, SearchConfig, SearchMode, SearchTool, StackOneToolSet
|
|
11
11
|
|
|
12
12
|
__all__ = [
|
|
13
13
|
"StackOneToolSet",
|
|
14
14
|
"StackOneTool",
|
|
15
15
|
"Tools",
|
|
16
|
+
"ExecuteToolsConfig",
|
|
16
17
|
"SearchConfig",
|
|
17
18
|
"SearchMode",
|
|
18
19
|
"SearchTool",
|
|
@@ -22,4 +23,4 @@ __all__ = [
|
|
|
22
23
|
"SemanticSearchResponse",
|
|
23
24
|
"SemanticSearchError",
|
|
24
25
|
]
|
|
25
|
-
__version__ = "2.
|
|
26
|
+
__version__ = "2.5.1"
|
|
@@ -414,21 +414,33 @@ class StackOneTool(BaseModel):
|
|
|
414
414
|
|
|
415
415
|
for name, details in self.parameters.properties.items():
|
|
416
416
|
python_type: type = str # Default to str
|
|
417
|
+
is_nullable = False
|
|
417
418
|
if isinstance(details, dict):
|
|
418
419
|
type_str = details.get("type", "string")
|
|
420
|
+
is_nullable = details.get("nullable", False)
|
|
419
421
|
if type_str == "number":
|
|
420
422
|
python_type = float
|
|
421
423
|
elif type_str == "integer":
|
|
422
424
|
python_type = int
|
|
423
425
|
elif type_str == "boolean":
|
|
424
426
|
python_type = bool
|
|
427
|
+
elif type_str == "object":
|
|
428
|
+
python_type = dict
|
|
429
|
+
elif type_str == "array":
|
|
430
|
+
python_type = list
|
|
425
431
|
|
|
426
|
-
|
|
432
|
+
if is_nullable:
|
|
433
|
+
field = Field(default=None, description=details.get("description", ""))
|
|
434
|
+
else:
|
|
435
|
+
field = Field(description=details.get("description", ""))
|
|
427
436
|
else:
|
|
428
437
|
field = Field(description="")
|
|
429
438
|
|
|
430
439
|
schema_props[name] = field
|
|
431
|
-
|
|
440
|
+
if is_nullable:
|
|
441
|
+
annotations[name] = python_type | None
|
|
442
|
+
else:
|
|
443
|
+
annotations[name] = python_type
|
|
432
444
|
|
|
433
445
|
# Create the schema class with proper annotations
|
|
434
446
|
schema_class = type(
|
|
@@ -12,18 +12,15 @@ Each path trades off between speed, filtering, and completeness.
|
|
|
12
12
|
This is the primary method used when integrating with OpenAI, LangChain, or CrewAI.
|
|
13
13
|
The internal flow is:
|
|
14
14
|
|
|
15
|
-
1. Fetch
|
|
16
|
-
2.
|
|
17
|
-
3.
|
|
18
|
-
4.
|
|
19
|
-
5.
|
|
20
|
-
6. Return Tools sorted by relevance score
|
|
15
|
+
1. Fetch tools from linked accounts via MCP (provides connectors and tool schemas)
|
|
16
|
+
2. Search EACH connector in parallel via the semantic search API (/actions/search)
|
|
17
|
+
3. Match search results to MCP tool definitions
|
|
18
|
+
4. Deduplicate, sort by relevance score, apply top_k
|
|
19
|
+
5. Return Tools sorted by relevance score
|
|
21
20
|
|
|
22
21
|
Key point: only the user's own connectors are searched — no wasted results
|
|
23
|
-
from connectors the user doesn't have.
|
|
24
|
-
|
|
25
|
-
accounts AND match the semantic query are returned. This prevents
|
|
26
|
-
suggesting tools the user cannot execute.
|
|
22
|
+
from connectors the user doesn't have. Tool schemas come from MCP (source
|
|
23
|
+
of truth), while the search API provides relevance ranking.
|
|
27
24
|
|
|
28
25
|
If the semantic API is unavailable, the SDK falls back to a local
|
|
29
26
|
BM25 + TF-IDF hybrid search over the fetched tools (unless
|
|
@@ -33,10 +30,9 @@ BM25 + TF-IDF hybrid search over the fetched tools (unless
|
|
|
33
30
|
2. ``search_action_names(query)`` — Lightweight discovery
|
|
34
31
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
35
32
|
|
|
36
|
-
Queries the semantic API directly and returns action
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
to a full fetch.
|
|
33
|
+
Queries the semantic API directly and returns action IDs with
|
|
34
|
+
similarity scores, **without** building full tool objects. Useful
|
|
35
|
+
for previewing results before committing to a full fetch.
|
|
40
36
|
|
|
41
37
|
When ``account_ids`` are provided, each connector is searched in
|
|
42
38
|
parallel (same as ``search_tools``). Without ``account_ids``, results
|
|
@@ -71,12 +67,8 @@ class SemanticSearchError(Exception):
|
|
|
71
67
|
class SemanticSearchResult(BaseModel):
|
|
72
68
|
"""Single result from semantic search API."""
|
|
73
69
|
|
|
74
|
-
|
|
75
|
-
connector_key: str
|
|
70
|
+
id: str
|
|
76
71
|
similarity_score: float
|
|
77
|
-
label: str
|
|
78
|
-
description: str
|
|
79
|
-
project_id: str = "global"
|
|
80
72
|
|
|
81
73
|
|
|
82
74
|
class SemanticSearchResponse(BaseModel):
|
|
@@ -99,7 +91,7 @@ class SemanticSearchClient:
|
|
|
99
91
|
client = SemanticSearchClient(api_key="sk-xxx")
|
|
100
92
|
response = client.search("create employee", connector="bamboohr", top_k=5)
|
|
101
93
|
for result in response.results:
|
|
102
|
-
print(f"{result.
|
|
94
|
+
print(f"{result.action_id}: {result.similarity_score:.2f}")
|
|
103
95
|
"""
|
|
104
96
|
|
|
105
97
|
def __init__(
|
|
@@ -152,7 +144,7 @@ class SemanticSearchClient:
|
|
|
152
144
|
Example:
|
|
153
145
|
response = client.search("onboard a new team member", top_k=5)
|
|
154
146
|
for result in response.results:
|
|
155
|
-
print(f"{result.
|
|
147
|
+
print(f"{result.action_id}: {result.similarity_score:.2f}")
|
|
156
148
|
"""
|
|
157
149
|
url = f"{self.base_url}/actions/search"
|
|
158
150
|
headers = {
|
|
@@ -210,4 +202,4 @@ class SemanticSearchClient:
|
|
|
210
202
|
)
|
|
211
203
|
"""
|
|
212
204
|
response = self.search(query, connector, top_k, project_id, min_similarity=min_similarity)
|
|
213
|
-
return [r.
|
|
205
|
+
return [r.id for r in response.results]
|