Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
abeef28
agent-*-advanced: wire up durable-resume branch of databricks-ai-bridge
dhruv0811 Apr 16, 2026
83a8e7e
Wire UI through LongRunningAgentServer's background+resume contract
dhruv0811 Apr 20, 2026
fa550af
Route AI SDK through Express /invocations proxy so background-rewrite…
dhruv0811 Apr 20, 2026
911f18b
Log response_id on first SSE event from Express proxy
dhruv0811 Apr 20, 2026
399ffde
Match API_PROXY + AGENT_BACKEND_URL in app.yaml too
dhruv0811 Apr 20, 2026
04e6b1b
start_app: point API_PROXY at the Express proxy, keep AGENT_BACKEND_U…
dhruv0811 Apr 20, 2026
948f7b4
Proxy: accept response_id from top-level, nested response.id, or id= …
dhruv0811 Apr 20, 2026
cea0508
Proxy: log upstream close + each resume-fetch attempt + final stream …
dhruv0811 Apr 20, 2026
cafd07d
Surface databricks_ai_bridge [durable] INFO logs into apps output
dhruv0811 Apr 20, 2026
4cbc677
Two-bubble UX on resume + match durable-resume wiring across templates
dhruv0811 Apr 20, 2026
a9c94c4
Heal orphan tool_calls in the OpenAI Session on every turn
dhruv0811 Apr 20, 2026
7f15d2f
Sanitize OpenAI session: dedupe + inject synthetic outputs in-place
dhruv0811 Apr 20, 2026
61dcfc0
Replace interrupted text with attempt 2's on durable resume
dhruv0811 Apr 20, 2026
75dae5d
Add debug logs for durable-resume data-resumed event propagation
dhruv0811 Apr 20, 2026
47a063f
Catch-all log in onData to trace which data parts reach client
dhruv0811 Apr 20, 2026
c27c016
Wipe text in-place on data-resumed instead of removing the part
dhruv0811 Apr 20, 2026
bfd8f6e
Post-stream truncate as belt-and-suspenders for durable-resume text wipe
dhruv0811 Apr 20, 2026
931ab0f
Post-stream truncate must create new part + message refs
dhruv0811 Apr 20, 2026
412e14f
Mid-stream text replacement via render-time slice in Messages
dhruv0811 Apr 20, 2026
89f096b
Merge remote-tracking branch 'origin/main' into dhruv0811/durable-exe…
dhruv0811 Apr 20, 2026
b17eec8
Remove debug console.logs from durable-resume UI path
dhruv0811 Apr 20, 2026
20f87cb
Use library-side durable-resume repair helpers
dhruv0811 Apr 21, 2026
0374ff4
Simplify: langgraph repair via middleware, UI minimal reset on resume
dhruv0811 Apr 21, 2026
e9b4064
debug: log response.resumed detection in chat.ts onChunk
dhruv0811 Apr 21, 2026
337c39f
debug: log every dataPart in chat.tsx onData to diagnose UI drop
dhruv0811 Apr 21, 2026
d144ec0
debug: log setMessages wipe details on data-resumed
dhruv0811 Apr 21, 2026
467d2ed
UI: render-time slice for durable-resume text wipe
dhruv0811 Apr 21, 2026
695dcfb
Simplify /invocations proxy: drop interruption suffix + writeEvent he…
dhruv0811 Apr 21, 2026
25202c7
Advanced templates: strip user-space durability code
dhruv0811 Apr 22, 2026
a912d8d
debug: disable UI wipe on data-resumed for observing inheritance
dhruv0811 Apr 22, 2026
4421511
Remove UI text-refresh plumbing now that server-side inheritance hand…
dhruv0811 Apr 23, 2026
7683079
Strip app-templates PR to the bare minimum durability surface
dhruv0811 Apr 23, 2026
5f3c507
chat: cap resume attempts per turn, don't reset on each chunk
dhruv0811 Apr 23, 2026
0ddbd60
Openai template: stable — per-type + per-call-id stream id tracking
dhruv0811 Apr 23, 2026
24140b3
Revert template-side durable-resume hardening; bridge fix suffices
dhruv0811 Apr 23, 2026
db9fb45
Refactor /invocations pumpStream into SSE parsing helpers
dhruv0811 Apr 23, 2026
9f7e95d
Default API_PROXY/AGENT_BACKEND_URL in chatbot, drop from advanced yaml
dhruv0811 Apr 23, 2026
ec73bc9
Restore API_PROXY line on advanced yaml files to match main
dhruv0811 Apr 23, 2026
0517e23
Fold getApiProxyUrl into request-context.ts
dhruv0811 Apr 23, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions agent-langgraph-advanced/agent_server/start_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,16 @@ def transform_stream_event(self, event, response_id):
poll_interval_seconds=float(os.getenv("POLL_INTERVAL_SECONDS", "1.0")),
)

log_level = os.getenv("LOG_LEVEL", "INFO")
_lvl = getattr(logging, log_level.upper(), logging.INFO)
logging.getLogger("agent_server").setLevel(_lvl)
# Surface [durable] lifecycle logs from LongRunningAgentServer into apps logs.
logging.getLogger("databricks_ai_bridge").setLevel(_lvl)
if not logging.getLogger().handlers:
logging.basicConfig(level=_lvl, format="%(asctime)s %(levelname)s %(name)s: %(message)s")
else:
logging.getLogger().setLevel(_lvl)

# Define the app as a module level variable to enable multiple workers
app = agent_server.app # noqa: F841
setup_mlflow_git_based_version_tracking()
Expand Down
6 changes: 6 additions & 0 deletions agent-langgraph-advanced/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,12 @@ setup = [
[tool.uv]
default-groups = ["dev", "setup"]

# TEMPORARY: point at the open PR branch while ML-64230 durable-resume
# changes are in review. Revert to the registry release once merged.
[tool.uv.sources]
databricks-ai-bridge = { git = "https://github.com/databricks/databricks-ai-bridge", branch = "dhruv0811/durable-execution-resume" }
databricks-langchain = { git = "https://github.com/databricks/databricks-ai-bridge", branch = "dhruv0811/durable-execution-resume", subdirectory = "integrations/langchain" }


[tool.pytest.ini_options]
base_url = "http://localhost:8000"
Expand Down
35 changes: 31 additions & 4 deletions agent-langgraph-advanced/scripts/start_app.py

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 12 additions & 1 deletion agent-openai-advanced/agent_server/start_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,18 @@ def transform_stream_event(self, event, response_id):
)

log_level = os.getenv("LOG_LEVEL", "INFO")
logging.getLogger("agent_server").setLevel(getattr(logging, log_level.upper(), logging.INFO))
_lvl = getattr(logging, log_level.upper(), logging.INFO)
logging.getLogger("agent_server").setLevel(_lvl)
# Surface [durable] lifecycle logs from LongRunningAgentServer into apps logs.
# These are INFO-level in databricks_ai_bridge but the library logger defaults
# to WARNING unless the host process sets it explicitly.
logging.getLogger("databricks_ai_bridge").setLevel(_lvl)
# Ensure the root handler actually emits at this level too. uvicorn sets up
# its own handlers for 'uvicorn.*' but leaves root untouched.
if not logging.getLogger().handlers:
logging.basicConfig(level=_lvl, format="%(asctime)s %(levelname)s %(name)s: %(message)s")
else:
logging.getLogger().setLevel(_lvl)

# Wrap the existing lifespan to ensure session tables are created before serving requests
_original_lifespan = agent_server.app.router.lifespan_context
Expand Down
6 changes: 6 additions & 0 deletions agent-openai-advanced/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,12 @@ setup = [
[tool.uv]
default-groups = ["dev", "setup"]

# TEMPORARY: point at the open PR branch while ML-64230 durable-resume
# changes are in review. Revert to the registry release once merged.
[tool.uv.sources]
databricks-ai-bridge = { git = "https://github.com/databricks/databricks-ai-bridge", branch = "dhruv0811/durable-execution-resume" }
databricks-openai = { git = "https://github.com/databricks/databricks-ai-bridge", branch = "dhruv0811/durable-execution-resume", subdirectory = "integrations/openai" }

[tool.pytest.ini_options]
base_url = "http://localhost:8000"
addopts = "-n 7"
Expand Down
35 changes: 31 additions & 4 deletions agent-openai-advanced/scripts/start_app.py

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@ import {
} from '@chat-template/auth';
import { createDatabricksProvider } from '@databricks/ai-sdk-provider';
import { extractReasoningMiddleware, wrapLanguageModel } from 'ai';
import { shouldInjectContextForEndpoint } from './request-context';
import {
getApiProxyUrl,
shouldInjectContextForEndpoint,
} from './request-context';

// Header keys for passing context through streamText headers
export const CONTEXT_HEADER_CONVERSATION_ID = 'x-databricks-conversation-id';
Expand Down Expand Up @@ -71,7 +74,7 @@ export async function getWorkspaceHostname(): Promise<string> {
// Environment variable to enable SSE logging
const LOG_SSE_EVENTS = process.env.LOG_SSE_EVENTS === 'true';

const API_PROXY = process.env.API_PROXY;
const API_PROXY = getApiProxyUrl();

// Cache for endpoint details to check task type and OBO scopes
const endpointDetailsCache = new Map<
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,28 @@
* Utility functions for request context handling.
*/

/**
* Resolve the URL the AI SDK provider should POST to, or ``undefined`` when
* the chatbot should talk directly to a Databricks serving endpoint.
*
* Resolution order:
* 1. Explicit ``API_PROXY`` env var — caller knows best.
* 2. ``DATABRICKS_SERVING_ENDPOINT`` set → direct-endpoint mode; no proxy.
* 3. Advanced-template default → route via this Node server's own
* ``/invocations`` proxy.
*/
export function getApiProxyUrl(): string | undefined {
if (process.env.API_PROXY) return process.env.API_PROXY;
if (process.env.DATABRICKS_SERVING_ENDPOINT) return undefined;
const port = process.env.CHAT_APP_PORT || process.env.PORT || '3000';
return `http://localhost:${port}/invocations`;
}

/**
* Determines whether context should be injected based on endpoint type.
*
* Context is injected when:
* 1. Using API_PROXY environment variable, OR
* 1. The Express /invocations proxy is in play (explicit or inferred), OR
* 2. Endpoint task type is 'agent/v2/chat' or 'agent/v1/responses'
*
* @param endpointTask - The task type of the serving endpoint (optional)
Expand All @@ -15,9 +32,7 @@
export function shouldInjectContextForEndpoint(
endpointTask: string | undefined,
): boolean {
const API_PROXY = process.env.API_PROXY;

if (API_PROXY) {
if (getApiProxyUrl()) {
return true;
}

Expand Down
Loading