timbal 2.2.0__tar.gz → 2.2.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.
- {timbal-2.2.0 → timbal-2.2.1}/PKG-INFO +1 -1
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/_version.py +2 -2
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/codegen/flow.py +14 -2
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/tools/krea.py +196 -160
- {timbal-2.2.0 → timbal-2.2.1}/.gitignore +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/LICENSE +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/README.md +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/docs/api-reference/ace/chat-completions.mdx +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/docs/api-reference/ace/create-from-workforce.mdx +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/docs/api-reference/ace/jobs/cancel.mdx +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/docs/api-reference/ace/jobs/get.mdx +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/docs/api-reference/ace/jobs/list.mdx +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/docs/api-reference/ace/jobs/retry.mdx +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/docs/api-reference/ace/link.mdx +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/docs/api-reference/ace/list-context-vars.mdx +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/docs/api-reference/ace/list-policies.mdx +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/docs/api-reference/ace/messages.mdx +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/docs/api-reference/ace/responses.mdx +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/docs/api-reference/ace/unlink.mdx +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/pyproject.toml +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/pyrightconfig.json +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/__init__.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/codegen/__init__.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/codegen/__main__.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/codegen/cli_utils.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/codegen/cst_utils.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/codegen/format.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/codegen/model_discovery.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/codegen/test.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/codegen/tool_discovery.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/codegen/transformers/__init__.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/codegen/transformers/add_edge.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/codegen/transformers/add_step.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/codegen/transformers/add_tool.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/codegen/transformers/remove_edge.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/codegen/transformers/remove_step.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/codegen/transformers/remove_tool.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/codegen/transformers/set_config.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/codegen/transformers/set_param.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/codegen/transformers/set_position.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/collectors/__init__.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/collectors/base.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/collectors/impl/__init__.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/collectors/impl/anthropic.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/collectors/impl/default.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/collectors/impl/message.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/collectors/impl/openai.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/collectors/impl/string.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/collectors/impl/timbal.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/collectors/registry.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/core/__init__.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/core/agent.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/core/fallback_model.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/core/llm_router.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/core/mcp.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/core/memory_compaction.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/core/models.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/core/runnable.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/core/skill.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/core/test_model.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/core/tool.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/core/tool_set.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/core/workflow.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/errors.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/evals/__init__.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/evals/cli.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/evals/display.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/evals/fixtures/agent.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/evals/fixtures/eval_examples.yaml +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/evals/fixtures/eval_flow_validators.yaml +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/evals/fixtures/eval_negations.yaml +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/evals/fixtures/eval_parallel.yaml +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/evals/fixtures/eval_subagent.yaml +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/evals/fixtures/eval_transforms.yaml +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/evals/fixtures/test_invalid_validator.yaml +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/evals/models.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/evals/runner.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/evals/utils.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/evals/validators/__init__.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/evals/validators/base.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/evals/validators/comparison_base.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/evals/validators/contains.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/evals/validators/contains_all.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/evals/validators/contains_any.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/evals/validators/context.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/evals/validators/email.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/evals/validators/ends_with.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/evals/validators/eq.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/evals/validators/gt.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/evals/validators/gte.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/evals/validators/json.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/evals/validators/language.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/evals/validators/length.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/evals/validators/llm_base.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/evals/validators/lt.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/evals/validators/lte.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/evals/validators/max_length.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/evals/validators/min_length.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/evals/validators/not_null.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/evals/validators/parallel.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/evals/validators/pattern.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/evals/validators/prompt.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/evals/validators/semantic.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/evals/validators/seq.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/evals/validators/starts_with.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/evals/validators/type.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/logs.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/models.yaml +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/platform/__init__.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/platform/integrations.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/platform/knowledge_bases/__init__.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/platform/knowledge_bases/query.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/platform/tool_proxy.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/platform/types.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/platform/utils.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/server/__init__.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/server/__main__.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/server/http.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/server/jobs.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/server/voice.html +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/server/voice.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/state/__init__.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/state/config.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/state/config_loader.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/state/context.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/state/dependency_analyzer.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/state/tracing/__init__.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/state/tracing/exporters/__init__.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/state/tracing/exporters/otel.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/state/tracing/providers/__init__.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/state/tracing/providers/base.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/state/tracing/providers/in_memory.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/state/tracing/providers/jsonl.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/state/tracing/providers/platform.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/state/tracing/providers/sqlite.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/state/tracing/span.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/state/tracing/trace.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/tools/__init__.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/tools/_creds.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/tools/asana.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/tools/bash.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/tools/cala.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/tools/cloudflare.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/tools/dynamics_business_central.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/tools/dynamics_sales.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/tools/edit.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/tools/elasticsearch.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/tools/elevenlabs.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/tools/excel.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/tools/fal.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/tools/fathom.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/tools/firecrawl.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/tools/gemini_images.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/tools/gmail.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/tools/google_analytics.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/tools/google_business.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/tools/google_calendar.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/tools/google_docs.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/tools/google_drive.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/tools/google_maps.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/tools/google_merchant_center.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/tools/google_search_console.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/tools/google_sheets.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/tools/happy_scribe.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/tools/hubspot.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/tools/interaction.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/tools/jira.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/tools/klaviyo.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/tools/knowledge_base.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/tools/lancedb.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/tools/linkedin.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/tools/mongodb.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/tools/netsuite.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/tools/onedrive.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/tools/outlook.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/tools/pinecone.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/tools/powerbi.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/tools/quiver_ai.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/tools/read.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/tools/replicate.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/tools/resend.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/tools/salesforce.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/tools/scraperapi.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/tools/sharepoint.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/tools/shopify.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/tools/slack.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/tools/stripe.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/tools/tavily.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/tools/web_search.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/tools/write.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/tools/xai.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/tools/zendesk.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/tools/zoho_crm.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/types/__init__.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/types/approval.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/types/content/__init__.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/types/content/base.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/types/content/custom.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/types/content/file.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/types/content/text.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/types/content/thinking.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/types/content/tool_result.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/types/content/tool_use.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/types/events/__init__.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/types/events/approval.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/types/events/base.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/types/events/delta.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/types/events/interaction.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/types/events/output.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/types/events/start.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/types/file.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/types/message.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/types/run_status.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/utils/__init__.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/utils/import_spec.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/utils/model.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/utils/net.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/utils/schema.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/utils/serialization.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/voice/__init__.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/voice/elevenlabs.py +0 -0
- {timbal-2.2.0 → timbal-2.2.1}/python/timbal/voice/session.py +0 -0
|
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
|
|
|
18
18
|
commit_id: str | None
|
|
19
19
|
__commit_id__: str | None
|
|
20
20
|
|
|
21
|
-
__version__ = version = '2.2.
|
|
22
|
-
__version_tuple__ = version_tuple = (2, 2,
|
|
21
|
+
__version__ = version = '2.2.1'
|
|
22
|
+
__version_tuple__ = version_tuple = (2, 2, 1)
|
|
23
23
|
|
|
24
24
|
__commit_id__ = commit_id = None
|
|
@@ -71,8 +71,20 @@ def _extract_key_from_lambda(fn: Any, source_step: str) -> str | None:
|
|
|
71
71
|
|
|
72
72
|
|
|
73
73
|
def _is_model_enum(values: list) -> bool:
|
|
74
|
-
"""Return True if
|
|
75
|
-
|
|
74
|
+
"""Return True if an enum is the canonical LLM model ID set (provider/name).
|
|
75
|
+
|
|
76
|
+
Matches against ``timbal.core.models.Model`` rather than guessing from shape:
|
|
77
|
+
other registries (e.g. Krea's image/video IDs) share the ``provider/name``
|
|
78
|
+
form but must keep their enum inline so editors resolve the right options.
|
|
79
|
+
"""
|
|
80
|
+
if len(values) <= 5 or not all(isinstance(v, str) and "/" in v for v in values[:5]):
|
|
81
|
+
return False
|
|
82
|
+
import typing
|
|
83
|
+
|
|
84
|
+
from timbal.core.models import Model
|
|
85
|
+
|
|
86
|
+
known = set(typing.get_args(Model))
|
|
87
|
+
return all(v in known for v in values)
|
|
76
88
|
|
|
77
89
|
|
|
78
90
|
def _compact_field(field: dict) -> dict:
|
|
@@ -26,6 +26,72 @@ _FAILED_STATUSES = frozenset({"failed", "cancelled"})
|
|
|
26
26
|
|
|
27
27
|
MediaKind = Literal["video", "image"]
|
|
28
28
|
|
|
29
|
+
# Model identifiers map directly to Krea's POST /generate/{media}/{provider}/{model} endpoints.
|
|
30
|
+
# Source of truth: https://api.krea.ai/openapi.json. Update when Krea adds/removes models.
|
|
31
|
+
KreaImageModel = Literal[
|
|
32
|
+
"bfl/flux-1-dev",
|
|
33
|
+
"bfl/flux-1-kontext-dev",
|
|
34
|
+
"bfl/flux-1.1-pro",
|
|
35
|
+
"bfl/flux-1.1-pro-ultra",
|
|
36
|
+
"bytedance/seededit",
|
|
37
|
+
"bytedance/seedream-4",
|
|
38
|
+
"bytedance/seedream-5-lite",
|
|
39
|
+
"google/imagen-3",
|
|
40
|
+
"google/imagen-4",
|
|
41
|
+
"google/imagen-4-fast",
|
|
42
|
+
"google/imagen-4-ultra",
|
|
43
|
+
"google/nano-banana",
|
|
44
|
+
"google/nano-banana-2",
|
|
45
|
+
"google/nano-banana-pro",
|
|
46
|
+
"ideogram/ideogram-2-turbo",
|
|
47
|
+
"ideogram/ideogram-3",
|
|
48
|
+
"krea/krea-2/large",
|
|
49
|
+
"krea/krea-2/medium",
|
|
50
|
+
"krea/krea-2/medium-turbo",
|
|
51
|
+
"luma/uni-1",
|
|
52
|
+
"openai/gpt-image",
|
|
53
|
+
"openai/gpt-image-2",
|
|
54
|
+
"qwen/2512",
|
|
55
|
+
"runway/gen-4-image",
|
|
56
|
+
"z-image/z-image",
|
|
57
|
+
]
|
|
58
|
+
|
|
59
|
+
KreaVideoModel = Literal[
|
|
60
|
+
"alibaba/wan-2.1",
|
|
61
|
+
"alibaba/wan-2.2",
|
|
62
|
+
"alibaba/wan-2.5",
|
|
63
|
+
"bytedance/seedance-1.0-pro",
|
|
64
|
+
"bytedance/seedance-1.0-pro-fast",
|
|
65
|
+
"bytedance/seedance-2",
|
|
66
|
+
"bytedance/seedance-2-fast",
|
|
67
|
+
"google/veo-2",
|
|
68
|
+
"google/veo-3",
|
|
69
|
+
"google/veo-3-fast",
|
|
70
|
+
"google/veo-3.1",
|
|
71
|
+
"google/veo-3.1-fast",
|
|
72
|
+
"google/veo-3.1-lite",
|
|
73
|
+
"kling/kling-1",
|
|
74
|
+
"kling/kling-1.5",
|
|
75
|
+
"kling/kling-1.6",
|
|
76
|
+
"kling/kling-2",
|
|
77
|
+
"kling/kling-2.1",
|
|
78
|
+
"kling/kling-2.5",
|
|
79
|
+
"kling/kling-2.6",
|
|
80
|
+
"kling/kling-3.0",
|
|
81
|
+
"kling/kling-o1",
|
|
82
|
+
"lightricks/ltx-video-2.3-22b",
|
|
83
|
+
"luma/ray-2",
|
|
84
|
+
"minimax/hailuo",
|
|
85
|
+
"minimax/hailuo-02",
|
|
86
|
+
"minimax/hailuo-2.3",
|
|
87
|
+
"minimax/hailuo-2.3-fast",
|
|
88
|
+
"runway/aleph",
|
|
89
|
+
"runway/gen-3",
|
|
90
|
+
"runway/gen-4-video",
|
|
91
|
+
"runway/gen-4.5",
|
|
92
|
+
"xai/grok-video",
|
|
93
|
+
]
|
|
94
|
+
|
|
29
95
|
|
|
30
96
|
def _krea_headers(api_key: str, *, webhook_url: str | None = None) -> dict[str, str]:
|
|
31
97
|
headers = {
|
|
@@ -248,9 +314,9 @@ class KreaGenerateVideo(Tool):
|
|
|
248
314
|
def __init__(self, **kwargs: Any) -> None:
|
|
249
315
|
async def _krea_generate_video(
|
|
250
316
|
prompt: str = Field(..., description="Text description of the video to generate."),
|
|
251
|
-
model:
|
|
317
|
+
model: KreaVideoModel = Field(
|
|
252
318
|
"google/veo-3.1-fast",
|
|
253
|
-
description="Krea video model
|
|
319
|
+
description="Krea video model as provider/model (e.g. google/veo-3.1-fast, kling/kling-2.5).",
|
|
254
320
|
),
|
|
255
321
|
aspect_ratio: str = Field("16:9", description="Aspect ratio when supported by the model."),
|
|
256
322
|
duration: int | None = Field(None, description="Duration in seconds when supported by the model."),
|
|
@@ -279,89 +345,74 @@ class KreaGenerateVideo(Tool):
|
|
|
279
345
|
start = time.monotonic()
|
|
280
346
|
resolved_model = model.strip()
|
|
281
347
|
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
api_key=api_key,
|
|
326
|
-
job_id=job_id,
|
|
327
|
-
poll_interval=poll_interval,
|
|
328
|
-
timeout=timeout,
|
|
329
|
-
)
|
|
330
|
-
|
|
331
|
-
urls = _extract_job_urls(job)
|
|
332
|
-
if not urls:
|
|
333
|
-
raise ValueError(f"No output URLs in completed Krea job: {job}")
|
|
334
|
-
|
|
335
|
-
elapsed = time.monotonic() - start
|
|
336
|
-
logger.info(
|
|
337
|
-
"Krea video generated",
|
|
338
|
-
model=resolved_model,
|
|
348
|
+
if not prompt or not prompt.strip():
|
|
349
|
+
raise ValueError("prompt is required and must be non-empty")
|
|
350
|
+
|
|
351
|
+
payload: dict[str, Any] = {"prompt": prompt.strip()}
|
|
352
|
+
if aspect_ratio:
|
|
353
|
+
payload["aspect_ratio"] = aspect_ratio
|
|
354
|
+
if duration is not None:
|
|
355
|
+
payload["duration"] = duration
|
|
356
|
+
if resolution is not None:
|
|
357
|
+
payload["resolution"] = resolution
|
|
358
|
+
if generate_audio is not None:
|
|
359
|
+
payload["generate_audio"] = generate_audio
|
|
360
|
+
if start_image:
|
|
361
|
+
payload["start_image"] = start_image
|
|
362
|
+
if end_image:
|
|
363
|
+
payload["end_image"] = end_image
|
|
364
|
+
if reference_images:
|
|
365
|
+
payload["reference_images"] = reference_images
|
|
366
|
+
if provider_params:
|
|
367
|
+
for key, value in provider_params.items():
|
|
368
|
+
if value is not None:
|
|
369
|
+
payload[key] = value
|
|
370
|
+
|
|
371
|
+
path = _build_generate_path("video", resolved_model)
|
|
372
|
+
api_key = await resolve_api_key(tool=self, provider_name="Krea", env_var="KREA_API_KEY")
|
|
373
|
+
import httpx
|
|
374
|
+
|
|
375
|
+
async with httpx.AsyncClient(timeout=httpx.Timeout(60.0, read=None)) as client:
|
|
376
|
+
submit = await client.post(
|
|
377
|
+
f"{_KREA_BASE}{path}",
|
|
378
|
+
headers=_krea_headers(api_key, webhook_url=webhook_url),
|
|
379
|
+
json=payload,
|
|
380
|
+
)
|
|
381
|
+
await _raise_for_krea_response(submit)
|
|
382
|
+
submit_data = submit.json()
|
|
383
|
+
|
|
384
|
+
job_id = submit_data.get("job_id")
|
|
385
|
+
if not isinstance(job_id, str) or not job_id:
|
|
386
|
+
raise ValueError(f"Krea video API returned no job_id: {submit_data}")
|
|
387
|
+
|
|
388
|
+
job = await _poll_krea_job(
|
|
389
|
+
client,
|
|
390
|
+
api_key=api_key,
|
|
339
391
|
job_id=job_id,
|
|
340
|
-
|
|
392
|
+
poll_interval=poll_interval,
|
|
393
|
+
timeout=timeout,
|
|
341
394
|
)
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
"elapsed_seconds": round(elapsed, 2),
|
|
364
|
-
}
|
|
395
|
+
|
|
396
|
+
urls = _extract_job_urls(job)
|
|
397
|
+
if not urls:
|
|
398
|
+
raise ValueError(f"No output URLs in completed Krea job: {job}")
|
|
399
|
+
|
|
400
|
+
elapsed = time.monotonic() - start
|
|
401
|
+
logger.info(
|
|
402
|
+
"Krea video generated",
|
|
403
|
+
model=resolved_model,
|
|
404
|
+
job_id=job_id,
|
|
405
|
+
elapsed_s=round(elapsed, 2),
|
|
406
|
+
)
|
|
407
|
+
return {
|
|
408
|
+
"success": True,
|
|
409
|
+
"model": resolved_model,
|
|
410
|
+
"job_id": job_id,
|
|
411
|
+
"video_url": urls[0],
|
|
412
|
+
"urls": urls,
|
|
413
|
+
"job": job,
|
|
414
|
+
"elapsed_seconds": round(elapsed, 2),
|
|
415
|
+
}
|
|
365
416
|
|
|
366
417
|
super().__init__(handler=_krea_generate_video, **kwargs)
|
|
367
418
|
|
|
@@ -385,9 +436,9 @@ class KreaGenerateImage(Tool):
|
|
|
385
436
|
def __init__(self, **kwargs: Any) -> None:
|
|
386
437
|
async def _krea_generate_image(
|
|
387
438
|
prompt: str = Field(..., description="Text description of the image to generate."),
|
|
388
|
-
model:
|
|
439
|
+
model: KreaImageModel = Field(
|
|
389
440
|
"bfl/flux-1-dev",
|
|
390
|
-
description="Krea image model
|
|
441
|
+
description="Krea image model as provider/model (e.g. bfl/flux-1-dev, krea/krea-2/large).",
|
|
391
442
|
),
|
|
392
443
|
width: int | None = Field(None, description="Output width in pixels when supported."),
|
|
393
444
|
height: int | None = Field(None, description="Output height in pixels when supported."),
|
|
@@ -407,82 +458,67 @@ class KreaGenerateImage(Tool):
|
|
|
407
458
|
start = time.monotonic()
|
|
408
459
|
resolved_model = model.strip()
|
|
409
460
|
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
api_key=api_key,
|
|
448
|
-
job_id=job_id,
|
|
449
|
-
poll_interval=poll_interval,
|
|
450
|
-
timeout=timeout,
|
|
451
|
-
)
|
|
452
|
-
|
|
453
|
-
urls = _extract_job_urls(job)
|
|
454
|
-
if not urls:
|
|
455
|
-
raise ValueError(f"No output URLs in completed Krea job: {job}")
|
|
456
|
-
|
|
457
|
-
elapsed = time.monotonic() - start
|
|
458
|
-
logger.info(
|
|
459
|
-
"Krea image generated",
|
|
460
|
-
model=resolved_model,
|
|
461
|
+
if not prompt or not prompt.strip():
|
|
462
|
+
raise ValueError("prompt is required and must be non-empty")
|
|
463
|
+
|
|
464
|
+
payload: dict[str, Any] = {"prompt": prompt.strip()}
|
|
465
|
+
if width is not None:
|
|
466
|
+
payload["width"] = width
|
|
467
|
+
if height is not None:
|
|
468
|
+
payload["height"] = height
|
|
469
|
+
if seed is not None:
|
|
470
|
+
payload["seed"] = seed
|
|
471
|
+
if image_url:
|
|
472
|
+
payload["image_url"] = image_url
|
|
473
|
+
if provider_params:
|
|
474
|
+
for key, value in provider_params.items():
|
|
475
|
+
if value is not None:
|
|
476
|
+
payload[key] = value
|
|
477
|
+
|
|
478
|
+
path = _build_generate_path("image", resolved_model)
|
|
479
|
+
api_key = await resolve_api_key(tool=self, provider_name="Krea", env_var="KREA_API_KEY")
|
|
480
|
+
import httpx
|
|
481
|
+
|
|
482
|
+
async with httpx.AsyncClient(timeout=httpx.Timeout(60.0, read=None)) as client:
|
|
483
|
+
submit = await client.post(
|
|
484
|
+
f"{_KREA_BASE}{path}",
|
|
485
|
+
headers=_krea_headers(api_key, webhook_url=webhook_url),
|
|
486
|
+
json=payload,
|
|
487
|
+
)
|
|
488
|
+
await _raise_for_krea_response(submit)
|
|
489
|
+
submit_data = submit.json()
|
|
490
|
+
|
|
491
|
+
job_id = submit_data.get("job_id")
|
|
492
|
+
if not isinstance(job_id, str) or not job_id:
|
|
493
|
+
raise ValueError(f"Krea image API returned no job_id: {submit_data}")
|
|
494
|
+
|
|
495
|
+
job = await _poll_krea_job(
|
|
496
|
+
client,
|
|
497
|
+
api_key=api_key,
|
|
461
498
|
job_id=job_id,
|
|
462
|
-
|
|
499
|
+
poll_interval=poll_interval,
|
|
500
|
+
timeout=timeout,
|
|
463
501
|
)
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
"elapsed_seconds": round(elapsed, 2),
|
|
486
|
-
}
|
|
502
|
+
|
|
503
|
+
urls = _extract_job_urls(job)
|
|
504
|
+
if not urls:
|
|
505
|
+
raise ValueError(f"No output URLs in completed Krea job: {job}")
|
|
506
|
+
|
|
507
|
+
elapsed = time.monotonic() - start
|
|
508
|
+
logger.info(
|
|
509
|
+
"Krea image generated",
|
|
510
|
+
model=resolved_model,
|
|
511
|
+
job_id=job_id,
|
|
512
|
+
elapsed_s=round(elapsed, 2),
|
|
513
|
+
)
|
|
514
|
+
return {
|
|
515
|
+
"success": True,
|
|
516
|
+
"model": resolved_model,
|
|
517
|
+
"job_id": job_id,
|
|
518
|
+
"image_url": urls[0],
|
|
519
|
+
"urls": urls,
|
|
520
|
+
"job": job,
|
|
521
|
+
"elapsed_seconds": round(elapsed, 2),
|
|
522
|
+
}
|
|
487
523
|
|
|
488
524
|
super().__init__(handler=_krea_generate_image, **kwargs)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|