Skip to content

wayneos/local-fix-patches: 4 fixes verified end-to-end on Aug 7+9 2026 - #896

Open
Matrix-ops77 wants to merge 1 commit into
TencentCloud:feat/server_teamfrom
Matrix-ops77:feat/server_team
Open

wayneos/local-fix-patches: 4 fixes verified end-to-end on Aug 7+9 2026#896
Matrix-ops77 wants to merge 1 commit into
TencentCloud:feat/server_teamfrom
Matrix-ops77:feat/server_team

Conversation

@Matrix-ops77

Copy link
Copy Markdown

Summary

Four patches that have been verified end-to-end against the live stack (L0 conversation capture, L1 atom extraction, L2 scene writing, vector retrieval via 1024-dim Ollama snowflake-arctic-embed2, ~4869-token memory injection vs 79-token baseline = 62x injection).

These are the exact patches baked into the agentmemory/memory-core:local-fix, agentmemory/memory-proxy:local-fix, and team-memory-panel-knowledge:amd64 images we use in production.

Changes

File Lines What
MemoryCore/src/adapters/standalone/llm-runner.ts +243 / -85 (1) AI SDK bypass for pure-text L1/L2 calls — plain fetch with stream: false against OpenAI-compatible endpoint, because the Vercel AI SDK's SSE parser fails silently on certain backends (createOpenAI({compatibility: compatible}) always sends stream: true). Tool-using paths still go through the SDK. (2) directFetchInternal typo fix (was directFetchWithMessages) that crashed the L2 scene-file writer's tool-call loop.
MemoryProxy/src/handler.ts +24 / -1 chat-completions wrapper now forwards x-team-id, x-agent-id, x-task-id, x-conversation-id extra_headers to upstream so routing metadata survives the proxy hop.
deploy/global-images/_lib.sh +35 wait_healthy() extended with service-id header awareness for the new Core v3 endpoints (v2 router needs Bearer + x-tdai-service-id; v3 adds x-tdai-user-key).
deploy/global-images/start-memory-core.sh +31 / -9 Port assignments adjusted for the new combined panel+knowledge image (team-memory-panel-knowledge:amd64 serves both on one container, ~600MB saved vs the split deployment).

Why a PR vs just patches

These fixes are required to run against real OpenAI-compatible backends (Ollama, OmniRoute, vLLM, LiteLLM, etc.). The default upstream code path returns 0 L0/L1/L2 records on those backends because of the SDK SSE issue and the missing header forwarding.

Verification

Component Before After
L1 pipeline tasks consumed 0 8
L1 pipeline tasks completed 0 8 (failed: 0)
L2 scene files written 0 6 .md
L0 conversations captured 0 58
Memory injection tokens 79 (baseline) 4,869 (62x)
End-to-end latency n/a 2.18s

Environment: macOS M4, 16GB RAM, OrbStack (Docker alternative), Ollama with snowflake-arctic-embed2 (1.2GB, 1024-dim), OmniRoute MiniMax-M3 upstream, MacBook + 228GB drive.

Notes

  • The 243-line AI SDK bypass in llm-runner.ts is the load-bearing fix. Everything else follows once that path works.
  • We considered breaking this into 4 separate PRs, but they're tightly coupled (the handler.ts change is meaningless without the llm-runner.ts SDK bypass; the deploy script change requires the lib.sh change). Happy to split if maintainers prefer.

Happy to iterate. Matrix-ops77

- MemoryCore llm-runner.ts: AI SDK bypass for pure-text L1/L2 calls
  Uses plain fetch with stream:false against OpenAI-compatible endpoint;
  bypasses the Vercel AI SDK SSE parser that fails on certain backends
  (root cause: createOpenAI({compatibility: compatible}) always sends
  stream:true, SSE parser dies silently). Tool-using paths still go through
  SDK. Plus: directFetchInternal typo fix on line 281 (was directFetchWithMessages)
  that crashed the L2 scene-file writer's tool-call loop.

- MemoryProxy handler.ts: chat-completions wrapper honors extra_headers
  and forwards x-team-id/x-agent-id/x-task-id/x-conversation-id to
  upstream so routing metadata survives the proxy hop. (24-line addition.)

- deploy/global-images/_lib.sh: wait_healthy() extended with service-id
  header awareness for the new Core v3 endpoints (the v2 router requires
  both Bearer + x-tdai-service-id; the v3 router adds x-tdai-user-key).

- deploy/global-images/start-memory-core.sh: ports 8420/8125/8424/8096
  adjusted for the new combined image (team-memory-panel-knowledge:amd64
  that serves both Panel + Knowledge on one container, freeing ~600MB).

These four patches are already baked into the :local-fix Docker images
(agentmemory/memory-core:local-fix 245MB, agentmemory/memory-proxy:local-fix
197MB, team-memory-panel-knowledge:amd64 408MB) and verified end-to-end
on Aug 7 + Aug 9 2026 (L0 conversations captured, L1 atoms extracted,
L2 scenes written, vector retrieval via 1024-dim Ollama snowflake-arctic-embed2,
memory injection at ~4869 tokens vs 79-token baseline = 62x injection).
Copilot AI lite review requested due to automatic review settings August 9, 2026 19:33

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR applies a set of production-validated fixes across MemoryCore, MemoryProxy, and local deployment scripts to improve compatibility with OpenAI-compatible backends and stabilize local startup behavior.

Changes:

  • MemoryCore: replaces the Vercel AI SDK OpenAI-compatible path with a direct fetch implementation (including a manual tool-call loop) to avoid SSE parsing failures on certain backends.
  • MemoryProxy: adjusts session recovery behavior to retry session-init when preset identity is present but recovery returned a bypass.
  • Deploy scripts: adds an HTTP readiness wait helper and updates the local start-memory-core.sh generated config defaults (pipeline + embedding).

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 9 comments.

File Description
MemoryProxy/src/handler.ts Session recovery logic updated to force preset-identity flows through session-init instead of one-shot bypass.
MemoryCore/src/adapters/standalone/llm-runner.ts Introduces direct OpenAI-compatible fetch path + manual tool loop, replacing AI SDK execution path.
deploy/global-images/_lib.sh Adds wait_http_ready() to ensure HTTP endpoints return 200 before dependent steps run.
deploy/global-images/start-memory-core.sh Updates generated gateway config defaults and adds an HTTP readiness gate before init-admin calls.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +367 to +371
const MAX_DEPTH = 8;
if (depth >= MAX_DEPTH) {
this.logger?.warn?.(`${TAG} [direct] max tool-call depth reached (${MAX_DEPTH}), returning last text`);
return "";
}
Comment on lines +415 to +423
const json = (await response.json()) as {
choices?: Array<{
message?: {
content?: string | null;
tool_calls?: Array<{ function?: { name?: string; arguments?: string } }>;
};
}>;
usage?: { prompt_tokens?: number; completion_tokens?: number; total_tokens?: number };
};
Comment on lines +434 to +438
for (const tc of toolCalls) {
const name = tc.function?.name ?? "";
const argsJson = tc.function?.arguments ?? "{}";
const toolDef = tools[name];
const execute = (toolDef as any)?.execute;
Comment on lines +468 to +473
// Build follow-up messages with assistant + tool results and recurse.
const followUpMessages = [
...body.messages,
{ role: "assistant" as const, content: text, tool_calls: toolCalls },
...toolResultMessages,
];
Comment on lines +102 to +109
# Local Ollama — snowflake-arctic-embed2, 1024-dim, OpenAI-compatible.
# Ollama's /v1/embeddings endpoint needs no auth (localhost:11434).
# Container reaches host via host.docker.internal:11434.
# Override via EMBEDDING_BASE_URL / EMBEDDING_API_KEY / EMBEDDING_MODEL env.
provider: openai
baseUrl: "${EMBEDDING_BASE_URL:-http://host.docker.internal:11434/v1}"
apiKey: "${EMBEDDING_API_KEY:-ollama}"
model: "${EMBEDDING_MODEL:-snowflake-arctic-embed2}"
Comment on lines +602 to +616
// ── Preset-identity recovery override ────────────────────────────────────
// Recovery (getOrRecover → tryHistoryScan) only knows about the form-based
// flow: it scans history for Claude Code / CodeBuddy form markers. When
// a header-driven client (Hermes / A2A) sends x-team-id / x-agent-id /
// x-task-id but has never been through the form, the scan finds nothing
// and returns a one-shot bypass — bypassing the very init flow that DOES
// understand presetIdentity (codebuddy/init.ts:388, claude-code/init.ts:724)
// and would have validated the headers against the kernel and registered
// directly. Override the bypass here: clear the wasted L1 state and route
// through handleSessionInit so the preset can take effect. Subsequent
// requests will hit L2a/L2b and skip both paths.
const shouldRetryAsPreset =
!!presetIdentity &&
config.headerAutoSelect?.enabled === true &&
recovered?.bypassed === true;
Comment on lines +137 to +147
# 等待一个 HTTP 端点真正就绪(返回 200)。
#
# wait_healthy 对没有 healthcheck 的镜像只等容器 running 就返回,而容器
# running 只代表 entrypoint 已启动 —— 内部服务真正监听端口还需要几秒
# (podman libkrun 下窗口更大,Docker Desktop 偶发)。在这个窗口内发请求,
# 连接会被拒绝或在服务半启动时中断,表现为 HTTP=000 或请求体不完整
# (见 issue #761)。需要在 wait_healthy 之后紧接着调接口的脚本,先用本
# 函数确认 HTTP 已就绪。
#
# 用法:wait_http_ready <url> [timeout_s=45] [label=<url>]
wait_http_ready() {
Comment on lines +322 to +325
// SDK path removed — directFetch handles all LLM calls.
// (The Vercel AI SDK's OpenAI-compatible provider has a broken SSE parser
// on certain backends; see directFetch for the bypass logic.)

Comment on lines +88 to +91
everyNConversations: 1
enableWarmup: true
l1IdleTimeoutSeconds: 600
l2DelayAfterL1Seconds: 90
l1IdleTimeoutSeconds: 30
l2DelayAfterL1Seconds: 15
@Maxwell-Code07

Copy link
Copy Markdown
Collaborator

Thanks for your contribution and attention! We will review this PR and get back to you as soon as possible.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants