fix(agent-run): tolerate goosed stdio MCP listing gaps during session reconcile.
Memind CI / Test, build, and release guards (push) Failing after 4s

Skip hot-adding stdio extensions goosed omits from /extensions, stabilize MCP
scope during session start, and wire chat intent routing into the agent-run worker.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
john
2026-08-01 20:02:33 +08:00
parent 9d78927d1b
commit cdc265d7e0
6 changed files with 202 additions and 68 deletions
+102 -56
View File
@@ -3,8 +3,13 @@ import fs from 'node:fs';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
import { createAgentRunGateway } from '../agent-run-gateway.mjs';
import { createManagedChatIntentRouter } from '../chat-intent-router.mjs';
import { createConversationMemoryService } from '../conversation-memory.mjs';
import { createDbPool } from '../db.mjs';
import { createEpisodicMemoryService } from '../episodic-memory.mjs';
import { createLlmProviderService } from '../llm-providers.mjs';
import { createMemoryV2AdminConfigService } from '../memory-v2-admin-config.mjs';
import { createManagedMemoryV2Runtime } from '../memory-v2-runtime.mjs';
import { createTkmindProxy } from '../tkmind-proxy.mjs';
import { createToolGateway } from '../tool-gateway.mjs';
import { createUserAuth } from '../user-auth.mjs';
@@ -94,62 +99,103 @@ if (args.help) {
process.exit(0);
}
const pool = createDbPool();
const workflowShadowEnabled = isEnabledFlag(
process.env.MEMIND_ORCHESTRATOR_SHADOW_OBSERVATION_ENABLED,
);
const workflowShadowObserver = workflowShadowEnabled
? createWorkflowShadowObserver({
configService: createOrchestratorAdminConfigService(pool),
serviceToken: process.env.MEMIND_ORCHESTRATOR_SERVICE_TOKEN,
})
: null;
const baseUserAuth = createUserAuth(pool, {
usersRoot: process.env.H5_USERS_ROOT ?? path.join(root, 'users'),
h5Root: root,
});
const overrideWorkingDir = String(process.env.MEMIND_AGENT_RUN_WORKDIR_OVERRIDE ?? '').trim();
const overrideWorkingDirUserId = String(process.env.MEMIND_AGENT_RUN_WORKDIR_USER_ID ?? '').trim();
const userAuth = overrideWorkingDir
? {
...baseUserAuth,
async resolveWorkingDir(userId) {
if (!overrideWorkingDirUserId || overrideWorkingDirUserId === userId) {
return path.resolve(overrideWorkingDir);
}
return baseUserAuth.resolveWorkingDir(userId);
},
}
: baseUserAuth;
const llmProviderService = createLlmProviderService(pool, {
apiTarget: process.env.TKMIND_API_TARGET ?? 'https://127.0.0.1:18006',
apiSecret: process.env.TKMIND_SERVER__SECRET_KEY ?? 'local-dev-secret',
});
const toolGateway = createToolGateway({ llmProviderService });
const apiTargets = parseTargets();
const tkmindProxy = createTkmindProxy({
apiTarget: apiTargets[0],
apiTargets,
apiSecret: process.env.TKMIND_SERVER__SECRET_KEY ?? 'local-dev-secret',
userAuth,
});
const gateway = createAgentRunGateway({
pool,
userAuth,
tkmindProxy,
toolGateway,
autoDispatch: false,
maxConcurrentRuns: Number(process.env.MEMIND_AGENT_RUN_QUEUE_CONCURRENCY ?? 1),
runTimeoutMs: Number(process.env.MEMIND_AGENT_RUN_TIMEOUT_MS ?? 15 * 60 * 1000),
observeWorkflowRun: workflowShadowObserver,
observeWorkflowValidation:
workflowShadowObserver?.observeValidation ?? null,
enforcePageDataWorkflowValidation:
workflowShadowEnabled
&& isEnabledFlag(
process.env.MEMIND_ORCHESTRATOR_PAGE_DATA_VALIDATION_GATE_ENABLED,
),
});
async function bootstrapWorker() {
const pool = createDbPool();
const workflowShadowEnabled = isEnabledFlag(
process.env.MEMIND_ORCHESTRATOR_SHADOW_OBSERVATION_ENABLED,
);
const workflowShadowObserver = workflowShadowEnabled
? createWorkflowShadowObserver({
configService: createOrchestratorAdminConfigService(pool),
serviceToken: process.env.MEMIND_ORCHESTRATOR_SERVICE_TOKEN,
})
: null;
const baseUserAuth = createUserAuth(pool, {
usersRoot: process.env.H5_USERS_ROOT ?? path.join(root, 'users'),
h5Root: root,
});
const overrideWorkingDir = String(process.env.MEMIND_AGENT_RUN_WORKDIR_OVERRIDE ?? '').trim();
const overrideWorkingDirUserId = String(process.env.MEMIND_AGENT_RUN_WORKDIR_USER_ID ?? '').trim();
const userAuth = overrideWorkingDir
? {
...baseUserAuth,
async resolveWorkingDir(userId) {
if (!overrideWorkingDirUserId || overrideWorkingDirUserId === userId) {
return path.resolve(overrideWorkingDir);
}
return baseUserAuth.resolveWorkingDir(userId);
},
}
: baseUserAuth;
const llmProviderService = createLlmProviderService(pool, {
apiTarget: process.env.TKMIND_API_TARGET ?? 'https://127.0.0.1:18006',
apiSecret: process.env.TKMIND_SERVER__SECRET_KEY ?? 'local-dev-secret',
});
const memoryV2ConfigService = createMemoryV2AdminConfigService(pool);
const getEffectiveEnv = async () => {
const state = await memoryV2ConfigService.getRuntimeState().catch(() => null);
return {
...process.env,
...(state?.overrides ?? {}),
};
};
const conversationMemoryService = createConversationMemoryService(pool, {
llmProviderService,
getEffectiveEnv,
});
const memoryV2 = await createManagedMemoryV2Runtime({
legacyMemoryService: conversationMemoryService,
configService: memoryV2ConfigService,
mysqlPool: pool,
});
const episodicMemoryService = createEpisodicMemoryService(pool, {
getEffectiveEnv,
logger: console,
});
await episodicMemoryService.ensureSchema().catch((err) => {
console.warn(
'[agent-run-worker] episodic memory schema setup degraded:',
err instanceof Error ? err.message : err,
);
});
const chatIntentRouter = createManagedChatIntentRouter({
llmProviderService,
memoryV2,
conversationMemoryService,
episodicMemoryService,
configService: memoryV2ConfigService,
});
const toolGateway = createToolGateway({ llmProviderService });
const apiTargets = parseTargets();
const tkmindProxy = createTkmindProxy({
apiTarget: apiTargets[0],
apiTargets,
apiSecret: process.env.TKMIND_SERVER__SECRET_KEY ?? 'local-dev-secret',
userAuth,
});
const gateway = createAgentRunGateway({
pool,
userAuth,
tkmindProxy,
toolGateway,
chatIntentRouter,
conversationMemoryService,
autoDispatch: false,
maxConcurrentRuns: Number(process.env.MEMIND_AGENT_RUN_QUEUE_CONCURRENCY ?? 1),
runTimeoutMs: Number(process.env.MEMIND_AGENT_RUN_TIMEOUT_MS ?? 15 * 60 * 1000),
observeWorkflowRun: workflowShadowObserver,
observeWorkflowValidation:
workflowShadowObserver?.observeValidation ?? null,
enforcePageDataWorkflowValidation:
workflowShadowEnabled
&& isEnabledFlag(
process.env.MEMIND_ORCHESTRATOR_PAGE_DATA_VALIDATION_GATE_ENABLED,
),
});
return { pool, gateway };
}
const { pool, gateway } = await bootstrapWorker();
let stopping = false;
process.on('SIGINT', () => { stopping = true; });