diff --git a/.gitignore b/.gitignore index 0ab0cbd2..22d3026d 100644 --- a/.gitignore +++ b/.gitignore @@ -23,9 +23,6 @@ coturn/ dograh_pcm_cache/ node_modules/ -# Local self-signed TLS for the remote stack (regenerate with ./generate_certificate.sh). -# NEVER commit the private key. -certs/ # Superpowers brainstorm mockups (local only) .superpowers/ docs/superpowers/ diff --git a/docker-compose.override.yaml b/docker-compose.override.yaml deleted file mode 100644 index b12a49c1..00000000 --- a/docker-compose.override.yaml +++ /dev/null @@ -1,18 +0,0 @@ -# Auto-generated by setup_remote.sh (build mode). -# Overrides docker-compose.yaml to build api and ui images from local source -# instead of pulling them from a registry. Remove this file to revert to -# pulling prebuilt images. -services: - api: - build: - context: . - dockerfile: api/Dockerfile - image: dograh-local/dograh-api:local - pull_policy: never - - ui: - build: - context: . - dockerfile: ui/Dockerfile - image: dograh-local/dograh-ui:local - pull_policy: never diff --git a/docker-compose.yaml b/docker-compose.yaml index fd2bc8c2..f66cb51d 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -145,7 +145,7 @@ services: environment: # Core application config ENVIRONMENT: "${ENVIRONMENT:-local}" - LOG_LEVEL: "DEBUG" + LOG_LEVEL: "INFO" # Set to "false" in .env to disable public signup (invite-only installs). ENABLE_SIGNUP: "${ENABLE_SIGNUP:-true}" @@ -326,45 +326,6 @@ services: networks: - app-network - # dograh-asterisk — SIP/ARI gateway. A remote VICIdial SIP-trunks in here; - # calls route to Stasis(dograh) and dograh's ari_manager (in the api container) - # takes over: it reaches ARI at http://dograh-asterisk:8088 and Asterisk - # streams externalMedia audio back to ws://api:8000/api/v1/telephony/ws/ari — - # both over this compose network, so ARI/8088 is deliberately NOT published. - asterisk: - build: - context: ./asterisk - dockerfile: Dockerfile - image: dograh-asterisk:22 - container_name: dograh-asterisk - restart: unless-stopped - # Asterisk is started with `-c` (interactive console). Without a TTY, its - # console read-loop hits instant EOF on stdin (/dev/null) and busy-spins, - # pinning a CPU core and spewing NUL bytes to stdout (77GB of logs in a day). - # Allocating a pty gives the console a blocking stdin, so it idles instead. - tty: true - stdin_open: true - logging: - driver: "json-file" - options: - max-size: "10m" - max-file: "3" - # Config is dir-mounted from ./asterisk/etc — edit the .conf files on the host - # and apply with `docker exec dograh-asterisk asterisk -rx "module reload - # res_pjsip.so"` (or `dialplan reload`), no image rebuild. Host-specific values - # (public IP, ARI password, ws URI, RTP ports) are set literally in those - # files, so there are no env vars to configure here. Transport/port changes - # still need a container restart. - volumes: - - ./asterisk/etc:/etc/asterisk - ports: - - "${ASTERISK_SIP_PORT:-5060}:5060/udp" # SIP signalling - - "10000-10020:10000-10020/udp" # RTP media (must match rtp.conf rtpstart/rtpend) - networks: - - app-network - depends_on: - - api - volumes: postgres_data: redis_data: diff --git a/generate_certificate.sh b/generate_certificate.sh deleted file mode 100755 index 62e1c778..00000000 --- a/generate_certificate.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/bash -mkdir -p certs -openssl req -x509 -nodes -newkey rsa:2048 \ - -keyout certs/local.key \ - -out certs/local.crt \ - -days 365 \ - -subj "/CN=3.150.115.69" diff --git a/sdk/python/src/dograh_sdk/_generated_models.py b/sdk/python/src/dograh_sdk/_generated_models.py index d406cbb7..0f9dddfb 100644 --- a/sdk/python/src/dograh_sdk/_generated_models.py +++ b/sdk/python/src/dograh_sdk/_generated_models.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: -# filename: dograh-openapi-XXXXXX.json.di0tn7Gw6b -# timestamp: 2026-07-15T13:20:43+00:00 +# filename: dograh-openapi-XXXXXX.json.lCHmKR9UAf +# timestamp: 2026-07-20T14:09:14+00:00 from __future__ import annotations @@ -39,6 +39,26 @@ class CallDispositionCodes(BaseModel): ) +class FallbackDestination(RootModel[str]): + root: Annotated[str, Field(max_length=255, title='Fallback Destination')] + """ + Optional provider-native fallback destination. + """ + + +class ContextDestinationRoute(BaseModel): + """ + Map one gathered-context value to an external-PBX destination. + """ + + context_value: Annotated[ + str, Field(max_length=255, min_length=1, title='Context Value') + ] + destination: Annotated[ + str, Field(max_length=255, min_length=1, title='Destination') + ] + + class Category(Enum): """ Tool category. Must match definition.type. @@ -199,6 +219,19 @@ class EndCallToolDefinition(BaseModel): """ +class ExternalPBXFieldMapping(BaseModel): + """ + Map one gathered-context value to a provider-native field. + """ + + context_path: Annotated[ + str, Field(max_length=255, min_length=1, title='Context Path') + ] + destination_field: Annotated[ + str, Field(pattern='^[A-Za-z][A-Za-z0-9_]{0,63}$', title='Destination Field') + ] + + class GraphConstraints(BaseModel): """ Per-node-type graph rules. WorkflowGraph enforces these at validation. @@ -536,11 +569,12 @@ class ToolResponse(BaseModel): class DestinationSource(Enum): """ - Whether transfer destination is static/template or resolved by HTTP. + Whether the destination is static/template, resolved by HTTP, or mapped from gathered context to an external-PBX destination. """ static = 'static' dynamic = 'dynamic' + context_mapping = 'context_mapping' class MessageType1(Enum): @@ -600,6 +634,10 @@ class WorkflowConfigurationDefaults(BaseModel): context_compaction_enabled: Annotated[ bool | None, Field(title='Context Compaction Enabled') ] = False + external_pbx_field_mappings: Annotated[ + list[ExternalPBXFieldMapping] | None, + Field(max_length=100, title='External Pbx Field Mappings'), + ] = None class WorkflowListResponse(BaseModel): @@ -636,6 +674,29 @@ class WorkflowResponse(BaseModel): workflow_uuid: Annotated[str | None, Field(title='Workflow Uuid')] = None +class ContextDestinationMappingConfig(BaseModel): + """ + Resolve an external-PBX destination from gathered context. + """ + + context_path: Annotated[ + str, Field(max_length=255, min_length=1, title='Context Path') + ] + """ + Gathered-context path or extracted-variable name used for routing. + """ + routes: Annotated[ + list[ContextDestinationRoute], + Field(max_length=100, min_length=1, title='Routes'), + ] + fallback_destination: Annotated[ + FallbackDestination | None, Field(title='Fallback Destination') + ] = None + """ + Optional provider-native fallback destination. + """ + + class DocumentListResponseSchema(BaseModel): """ Response schema for list of documents. @@ -827,7 +888,7 @@ class TransferCallConfig(BaseModel): DestinationSource | None, Field(title='Destination Source') ] = 'static' """ - Whether transfer destination is static/template or resolved by HTTP. + Whether the destination is static/template, resolved by HTTP, or mapped from gathered context to an external-PBX destination. """ destination: Annotated[str | None, Field(title='Destination')] = '' """ @@ -857,6 +918,10 @@ class TransferCallConfig(BaseModel): """ Optional resolver that determines transfer routing at call time. """ + context_mapping: ContextDestinationMappingConfig | None = None + """ + Optional gathered-context to external-PBX destination mapping. + """ class TransferCallToolDefinition(BaseModel): diff --git a/sdk/typescript/src/_generated_models.ts b/sdk/typescript/src/_generated_models.ts index f1c32b6c..0a9d4fad 100644 --- a/sdk/typescript/src/_generated_models.ts +++ b/sdk/typescript/src/_generated_models.ts @@ -312,6 +312,34 @@ export interface components { */ disposition_codes: string[]; }; + /** + * ContextDestinationMappingConfig + * @description Resolve an external-PBX destination from gathered context. + */ + ContextDestinationMappingConfig: { + /** + * Context Path + * @description Gathered-context path or extracted-variable name used for routing. + */ + context_path: string; + /** Routes */ + routes: components["schemas"]["ContextDestinationRoute"][]; + /** + * Fallback Destination + * @description Optional provider-native fallback destination. + */ + fallback_destination?: string | null; + }; + /** + * ContextDestinationRoute + * @description Map one gathered-context value to an external-PBX destination. + */ + ContextDestinationRoute: { + /** Context Value */ + context_value: string; + /** Destination */ + destination: string; + }; /** * CreateToolRequest * @description Request schema for creating a reusable tool. @@ -538,6 +566,16 @@ export interface components { /** @description End Call configuration. */ config: components["schemas"]["EndCallConfig"]; }; + /** + * ExternalPBXFieldMapping + * @description Map one gathered-context value to a provider-native field. + */ + ExternalPBXFieldMapping: { + /** Context Path */ + context_path: string; + /** Destination Field */ + destination_field: string; + }; /** * GraphConstraints * @description Per-node-type graph rules. WorkflowGraph enforces these at validation. @@ -1092,11 +1130,11 @@ export interface components { TransferCallConfig: { /** * Destination Source - * @description Whether transfer destination is static/template or resolved by HTTP. + * @description Whether the destination is static/template, resolved by HTTP, or mapped from gathered context to an external-PBX destination. * @default static * @enum {string} */ - destination_source: "static" | "dynamic"; + destination_source: "static" | "dynamic" | "context_mapping"; /** * Destination * @description Phone number, SIP endpoint, or template to transfer the call to, e.g. +1234567890, PJSIP/1234, or {{initial_context.transfer_destination}}. @@ -1133,6 +1171,8 @@ export interface components { parameters?: components["schemas"]["ToolParameter"][] | null; /** @description Optional resolver that determines transfer routing at call time. */ resolver?: components["schemas"]["HttpTransferResolverConfig"] | null; + /** @description Optional gathered-context to external-PBX destination mapping. */ + context_mapping?: components["schemas"]["ContextDestinationMappingConfig"] | null; }; /** * TransferCallToolDefinition @@ -1230,6 +1270,8 @@ export interface components { * @default false */ context_compaction_enabled: boolean; + /** External Pbx Field Mappings */ + external_pbx_field_mappings?: components["schemas"]["ExternalPBXFieldMapping"][]; } & { [key: string]: unknown; }; @@ -1303,6 +1345,8 @@ export interface components { export type AmbientNoiseConfigurationDefaults = components['schemas']['AmbientNoiseConfigurationDefaults']; export type CalculatorToolDefinition = components['schemas']['CalculatorToolDefinition']; export type CallDispositionCodes = components['schemas']['CallDispositionCodes']; +export type ContextDestinationMappingConfig = components['schemas']['ContextDestinationMappingConfig']; +export type ContextDestinationRoute = components['schemas']['ContextDestinationRoute']; export type CreateToolRequest = components['schemas']['CreateToolRequest']; export type CreateWorkflowRequest = components['schemas']['CreateWorkflowRequest']; export type CreatedByResponse = components['schemas']['CreatedByResponse']; @@ -1312,6 +1356,7 @@ export type DocumentListResponseSchema = components['schemas']['DocumentListResp export type DocumentResponseSchema = components['schemas']['DocumentResponseSchema']; export type EndCallConfig = components['schemas']['EndCallConfig']; export type EndCallToolDefinition = components['schemas']['EndCallToolDefinition']; +export type ExternalPbxFieldMapping = components['schemas']['ExternalPBXFieldMapping']; export type GraphConstraints = components['schemas']['GraphConstraints']; export type HttpValidationError = components['schemas']['HTTPValidationError']; export type HttpApiConfig = components['schemas']['HttpApiConfig'];