mirror of
https://github.com/dograh-hq/dograh.git
synced 2026-06-10 08:05:22 +02:00
feat: refactor node spec and add mcp tools (#244)
* refactor: carve out extraction panel * refactor: create spec versions for node types * refactor: create a GenericNode and remove custom nodes * feat: add python and typescript sdk * add dograh sdk * fix: fetch draft workflow definition over published one * fix: fix routes of SDKs to use code gen * chore: remove doclink dependency to reduce image size * chore: format files * chore: bump pipecat * feat: let mcp fetch archived workflows on demand * chore: fix tests * feat: add sdk documentation * chore: change banner and add badge
This commit is contained in:
parent
0a61ef295f
commit
00a1a22b74
162 changed files with 14355 additions and 3554 deletions
358
sdk/python/src/dograh_sdk/_generated_models.py
Normal file
358
sdk/python/src/dograh_sdk/_generated_models.py
Normal file
|
|
@ -0,0 +1,358 @@
|
|||
# generated by datamodel-codegen:
|
||||
# filename: dograh-openapi-XXXXXX.json.oPRfLAwVZP
|
||||
# timestamp: 2026-04-21T02:15:12+00:00
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from enum import Enum
|
||||
from typing import Annotated, Any
|
||||
|
||||
from pydantic import AwareDatetime, BaseModel, ConfigDict, Field
|
||||
|
||||
|
||||
class CallDispositionCodes(BaseModel):
|
||||
disposition_codes: Annotated[list[str] | None, Field(title='Disposition Codes')] = (
|
||||
[]
|
||||
)
|
||||
|
||||
|
||||
class CreatedByResponse(BaseModel):
|
||||
"""
|
||||
Response schema for the user who created a tool.
|
||||
"""
|
||||
|
||||
id: Annotated[int, Field(title='Id')]
|
||||
provider_id: Annotated[str, Field(title='Provider Id')]
|
||||
|
||||
|
||||
class CredentialResponse(BaseModel):
|
||||
"""
|
||||
Response schema for a webhook credential (never includes sensitive data).
|
||||
"""
|
||||
|
||||
uuid: Annotated[str, Field(title='Uuid')]
|
||||
name: Annotated[str, Field(title='Name')]
|
||||
description: Annotated[str | None, Field(title='Description')]
|
||||
credential_type: Annotated[str, Field(title='Credential Type')]
|
||||
created_at: Annotated[AwareDatetime, Field(title='Created At')]
|
||||
updated_at: Annotated[AwareDatetime | None, Field(title='Updated At')]
|
||||
|
||||
|
||||
class DisplayOptions(BaseModel):
|
||||
"""
|
||||
Conditional visibility rules.
|
||||
|
||||
`show` keys are AND-combined: this property is visible only when EVERY
|
||||
referenced field's value matches one of the listed values.
|
||||
|
||||
`hide` keys are OR-combined: this property is hidden when ANY referenced
|
||||
field's value matches one of the listed values.
|
||||
|
||||
Example:
|
||||
DisplayOptions(show={"extraction_enabled": [True]})
|
||||
DisplayOptions(show={"greeting_type": ["audio"]})
|
||||
"""
|
||||
|
||||
model_config = ConfigDict(
|
||||
extra='forbid',
|
||||
)
|
||||
show: Annotated[dict[str, list[Any]] | None, Field(title='Show')] = None
|
||||
hide: Annotated[dict[str, list[Any]] | None, Field(title='Hide')] = None
|
||||
|
||||
|
||||
class DocumentResponseSchema(BaseModel):
|
||||
"""
|
||||
Response schema for document metadata.
|
||||
"""
|
||||
|
||||
id: Annotated[int, Field(title='Id')]
|
||||
document_uuid: Annotated[str, Field(title='Document Uuid')]
|
||||
filename: Annotated[str, Field(title='Filename')]
|
||||
file_size_bytes: Annotated[int, Field(title='File Size Bytes')]
|
||||
file_hash: Annotated[str, Field(title='File Hash')]
|
||||
mime_type: Annotated[str, Field(title='Mime Type')]
|
||||
processing_status: Annotated[str, Field(title='Processing Status')]
|
||||
processing_error: Annotated[str | None, Field(title='Processing Error')] = None
|
||||
total_chunks: Annotated[int, Field(title='Total Chunks')]
|
||||
retrieval_mode: Annotated[str | None, Field(title='Retrieval Mode')] = 'chunked'
|
||||
custom_metadata: Annotated[dict[str, Any], Field(title='Custom Metadata')]
|
||||
docling_metadata: Annotated[dict[str, Any], Field(title='Docling Metadata')]
|
||||
source_url: Annotated[str | None, Field(title='Source Url')] = None
|
||||
created_at: Annotated[AwareDatetime, Field(title='Created At')]
|
||||
updated_at: Annotated[AwareDatetime, Field(title='Updated At')]
|
||||
organization_id: Annotated[int, Field(title='Organization Id')]
|
||||
created_by: Annotated[int, Field(title='Created By')]
|
||||
is_active: Annotated[bool, Field(title='Is Active')]
|
||||
|
||||
|
||||
class GraphConstraints(BaseModel):
|
||||
"""
|
||||
Per-node-type graph rules. WorkflowGraph enforces these at validation.
|
||||
"""
|
||||
|
||||
model_config = ConfigDict(
|
||||
extra='forbid',
|
||||
)
|
||||
min_incoming: Annotated[int | None, Field(title='Min Incoming')] = None
|
||||
max_incoming: Annotated[int | None, Field(title='Max Incoming')] = None
|
||||
min_outgoing: Annotated[int | None, Field(title='Min Outgoing')] = None
|
||||
max_outgoing: Annotated[int | None, Field(title='Max Outgoing')] = None
|
||||
|
||||
|
||||
class InitiateCallRequest(BaseModel):
|
||||
workflow_id: Annotated[int, Field(title='Workflow Id')]
|
||||
workflow_run_id: Annotated[int | None, Field(title='Workflow Run Id')] = None
|
||||
phone_number: Annotated[str | None, Field(title='Phone Number')] = None
|
||||
|
||||
|
||||
class NodeCategory(Enum):
|
||||
"""
|
||||
Drives grouping in the AddNodePanel UI.
|
||||
"""
|
||||
|
||||
call_node = 'call_node'
|
||||
global_node = 'global_node'
|
||||
trigger = 'trigger'
|
||||
integration = 'integration'
|
||||
|
||||
|
||||
class NodeExample(BaseModel):
|
||||
"""
|
||||
A worked example LLMs can pattern-match. Keep small and realistic.
|
||||
"""
|
||||
|
||||
model_config = ConfigDict(
|
||||
extra='forbid',
|
||||
)
|
||||
name: Annotated[str, Field(title='Name')]
|
||||
description: Annotated[str | None, Field(title='Description')] = None
|
||||
data: Annotated[dict[str, Any], Field(title='Data')]
|
||||
|
||||
|
||||
class PropertyOption(BaseModel):
|
||||
"""
|
||||
An option in an `options` or `multi_options` dropdown.
|
||||
"""
|
||||
|
||||
model_config = ConfigDict(
|
||||
extra='forbid',
|
||||
)
|
||||
value: Annotated[str | int | bool | float, Field(title='Value')]
|
||||
label: Annotated[str, Field(title='Label')]
|
||||
description: Annotated[str | None, Field(title='Description')] = None
|
||||
|
||||
|
||||
class PropertyType(Enum):
|
||||
"""
|
||||
Bounded vocabulary of property types the renderer dispatches on.
|
||||
|
||||
Adding a value here requires a matching arm in the frontend
|
||||
`<PropertyInput>` switch and (where relevant) the SDK codegen template.
|
||||
"""
|
||||
|
||||
string = 'string'
|
||||
number = 'number'
|
||||
boolean = 'boolean'
|
||||
options = 'options'
|
||||
multi_options = 'multi_options'
|
||||
fixed_collection = 'fixed_collection'
|
||||
json = 'json'
|
||||
tool_refs = 'tool_refs'
|
||||
document_refs = 'document_refs'
|
||||
recording_ref = 'recording_ref'
|
||||
credential_ref = 'credential_ref'
|
||||
mention_textarea = 'mention_textarea'
|
||||
url = 'url'
|
||||
|
||||
|
||||
class RecordingResponseSchema(BaseModel):
|
||||
"""
|
||||
Response schema for a single recording.
|
||||
"""
|
||||
|
||||
id: Annotated[int, Field(title='Id')]
|
||||
recording_id: Annotated[str, Field(title='Recording Id')]
|
||||
workflow_id: Annotated[int | None, Field(title='Workflow Id')] = None
|
||||
organization_id: Annotated[int, Field(title='Organization Id')]
|
||||
tts_provider: Annotated[str | None, Field(title='Tts Provider')] = None
|
||||
tts_model: Annotated[str | None, Field(title='Tts Model')] = None
|
||||
tts_voice_id: Annotated[str | None, Field(title='Tts Voice Id')] = None
|
||||
transcript: Annotated[str, Field(title='Transcript')]
|
||||
storage_key: Annotated[str, Field(title='Storage Key')]
|
||||
storage_backend: Annotated[str, Field(title='Storage Backend')]
|
||||
metadata: Annotated[dict[str, Any], Field(title='Metadata')]
|
||||
created_by: Annotated[int, Field(title='Created By')]
|
||||
created_at: Annotated[AwareDatetime, Field(title='Created At')]
|
||||
is_active: Annotated[bool, Field(title='Is Active')]
|
||||
|
||||
|
||||
class ToolResponse(BaseModel):
|
||||
"""
|
||||
Response schema for a tool.
|
||||
"""
|
||||
|
||||
id: Annotated[int, Field(title='Id')]
|
||||
tool_uuid: Annotated[str, Field(title='Tool Uuid')]
|
||||
name: Annotated[str, Field(title='Name')]
|
||||
description: Annotated[str | None, Field(title='Description')]
|
||||
category: Annotated[str, Field(title='Category')]
|
||||
icon: Annotated[str | None, Field(title='Icon')]
|
||||
icon_color: Annotated[str | None, Field(title='Icon Color')]
|
||||
status: Annotated[str, Field(title='Status')]
|
||||
definition: Annotated[dict[str, Any], Field(title='Definition')]
|
||||
created_at: Annotated[AwareDatetime, Field(title='Created At')]
|
||||
updated_at: Annotated[AwareDatetime | None, Field(title='Updated At')]
|
||||
created_by: CreatedByResponse | None = None
|
||||
|
||||
|
||||
class UpdateWorkflowRequest(BaseModel):
|
||||
name: Annotated[str | None, Field(title='Name')] = None
|
||||
workflow_definition: Annotated[
|
||||
dict[str, Any] | None, Field(title='Workflow Definition')
|
||||
] = None
|
||||
template_context_variables: Annotated[
|
||||
dict[str, Any] | None, Field(title='Template Context Variables')
|
||||
] = None
|
||||
workflow_configurations: Annotated[
|
||||
dict[str, Any] | None, Field(title='Workflow Configurations')
|
||||
] = None
|
||||
|
||||
|
||||
class ValidationError(BaseModel):
|
||||
loc: Annotated[list[str | int], Field(title='Location')]
|
||||
msg: Annotated[str, Field(title='Message')]
|
||||
type: Annotated[str, Field(title='Error Type')]
|
||||
input: Annotated[Any | None, Field(title='Input')] = None
|
||||
ctx: Annotated[dict[str, Any] | None, Field(title='Context')] = None
|
||||
|
||||
|
||||
class WorkflowListResponse(BaseModel):
|
||||
"""
|
||||
Lightweight response for workflow listings (excludes large fields).
|
||||
"""
|
||||
|
||||
id: Annotated[int, Field(title='Id')]
|
||||
name: Annotated[str, Field(title='Name')]
|
||||
status: Annotated[str, Field(title='Status')]
|
||||
created_at: Annotated[AwareDatetime, Field(title='Created At')]
|
||||
total_runs: Annotated[int, Field(title='Total Runs')]
|
||||
|
||||
|
||||
class WorkflowResponse(BaseModel):
|
||||
id: Annotated[int, Field(title='Id')]
|
||||
name: Annotated[str, Field(title='Name')]
|
||||
status: Annotated[str, Field(title='Status')]
|
||||
created_at: Annotated[AwareDatetime, Field(title='Created At')]
|
||||
workflow_definition: Annotated[dict[str, Any], Field(title='Workflow Definition')]
|
||||
current_definition_id: Annotated[int | None, Field(title='Current Definition Id')]
|
||||
template_context_variables: Annotated[
|
||||
dict[str, Any] | None, Field(title='Template Context Variables')
|
||||
] = None
|
||||
call_disposition_codes: CallDispositionCodes | None = None
|
||||
total_runs: Annotated[int | None, Field(title='Total Runs')] = None
|
||||
workflow_configurations: Annotated[
|
||||
dict[str, Any] | None, Field(title='Workflow Configurations')
|
||||
] = None
|
||||
version_number: Annotated[int | None, Field(title='Version Number')] = None
|
||||
version_status: Annotated[str | None, Field(title='Version Status')] = None
|
||||
|
||||
|
||||
class DocumentListResponseSchema(BaseModel):
|
||||
"""
|
||||
Response schema for list of documents.
|
||||
"""
|
||||
|
||||
documents: Annotated[list[DocumentResponseSchema], Field(title='Documents')]
|
||||
total: Annotated[int, Field(title='Total')]
|
||||
limit: Annotated[int, Field(title='Limit')]
|
||||
offset: Annotated[int, Field(title='Offset')]
|
||||
|
||||
|
||||
class HTTPValidationError(BaseModel):
|
||||
detail: Annotated[list[ValidationError] | None, Field(title='Detail')] = None
|
||||
|
||||
|
||||
class PropertySpec(BaseModel):
|
||||
"""
|
||||
Single field on a node.
|
||||
|
||||
`description` is HUMAN-FACING — shown under the field in the edit
|
||||
dialog. Keep it concise and explain what the field does.
|
||||
|
||||
`llm_hint` is LLM-FACING — appears only in the `get_node_type` MCP
|
||||
response and in SDK schema output. Use it for catalog tool references
|
||||
(e.g., "Use `list_recordings`"), array shape, expected value idioms,
|
||||
or anything that would be noise in the UI. Optional; omit when the
|
||||
`description` already suffices for both audiences.
|
||||
"""
|
||||
|
||||
model_config = ConfigDict(
|
||||
extra='forbid',
|
||||
)
|
||||
name: Annotated[str, Field(title='Name')]
|
||||
type: PropertyType
|
||||
display_name: Annotated[str, Field(title='Display Name')]
|
||||
description: Annotated[str, Field(min_length=1, title='Description')]
|
||||
"""
|
||||
Human-facing explanation shown in the UI.
|
||||
"""
|
||||
llm_hint: Annotated[str | None, Field(title='Llm Hint')] = None
|
||||
"""
|
||||
LLM-only guidance; omitted from the UI.
|
||||
"""
|
||||
default: Annotated[Any | None, Field(title='Default')] = None
|
||||
required: Annotated[bool | None, Field(title='Required')] = False
|
||||
placeholder: Annotated[str | None, Field(title='Placeholder')] = None
|
||||
display_options: DisplayOptions | None = None
|
||||
options: Annotated[list[PropertyOption] | None, Field(title='Options')] = None
|
||||
properties: Annotated[list[PropertySpec] | None, Field(title='Properties')] = None
|
||||
min_value: Annotated[float | None, Field(title='Min Value')] = None
|
||||
max_value: Annotated[float | None, Field(title='Max Value')] = None
|
||||
min_length: Annotated[int | None, Field(title='Min Length')] = None
|
||||
max_length: Annotated[int | None, Field(title='Max Length')] = None
|
||||
pattern: Annotated[str | None, Field(title='Pattern')] = None
|
||||
editor: Annotated[str | None, Field(title='Editor')] = None
|
||||
extra: Annotated[dict[str, Any] | None, Field(title='Extra')] = None
|
||||
|
||||
|
||||
class RecordingListResponseSchema(BaseModel):
|
||||
"""
|
||||
Response schema for list of recordings.
|
||||
"""
|
||||
|
||||
recordings: Annotated[list[RecordingResponseSchema], Field(title='Recordings')]
|
||||
total: Annotated[int, Field(title='Total')]
|
||||
|
||||
|
||||
class NodeSpec(BaseModel):
|
||||
"""
|
||||
Single source of truth for a node type.
|
||||
"""
|
||||
|
||||
model_config = ConfigDict(
|
||||
extra='forbid',
|
||||
)
|
||||
name: Annotated[str, Field(title='Name')]
|
||||
display_name: Annotated[str, Field(title='Display Name')]
|
||||
description: Annotated[str, Field(min_length=1, title='Description')]
|
||||
"""
|
||||
Human-facing explanation shown in AddNodePanel.
|
||||
"""
|
||||
llm_hint: Annotated[str | None, Field(title='Llm Hint')] = None
|
||||
"""
|
||||
LLM-only guidance; omitted from the UI.
|
||||
"""
|
||||
category: NodeCategory
|
||||
icon: Annotated[str, Field(title='Icon')]
|
||||
version: Annotated[str | None, Field(title='Version')] = '1.0.0'
|
||||
properties: Annotated[list[PropertySpec], Field(title='Properties')]
|
||||
examples: Annotated[list[NodeExample] | None, Field(title='Examples')] = None
|
||||
graph_constraints: GraphConstraints | None = None
|
||||
|
||||
|
||||
class NodeTypesResponse(BaseModel):
|
||||
spec_version: Annotated[str, Field(title='Spec Version')]
|
||||
node_types: Annotated[list[NodeSpec], Field(title='Node Types')]
|
||||
|
||||
|
||||
PropertySpec.model_rebuild()
|
||||
Loading…
Add table
Add a link
Reference in a new issue