Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 4 additions & 0 deletions config/examples/weixin.service.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -86,5 +86,9 @@ CODEX_NATIVE_API_ENABLE=1
# CODEXBRIDGE_INTERNAL_NATIVE_API_AUTH_TOKEN=replace-with-a-long-random-secret
# CODEXBRIDGE_INTERNAL_NATIVE_API_TASK_CLASSES=intent_classification,normalization,small_verification,side_reasoning

# Weixin delivery behavior. Disabled by default so Weixin receives one final
# answer instead of streamed preview snippets plus a final commit.
# CODEXBRIDGE_WEIXIN_PROGRESS_DELIVERY=0

# Debugging
CODEXBRIDGE_DEBUG_WEIXIN=0
1 change: 1 addition & 0 deletions src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,7 @@ async function runWeixinServe(args: string[]) {
automationJobs: runtime.services.automationJobs,
agentJobs: runtime.services.agentJobs,
assistantRecords: runtime.services.assistantRecords,
progressDeliveryEnabled: parseBooleanEnv(process.env.CODEXBRIDGE_WEIXIN_PROGRESS_DELIVERY, false),
onError: (async (error: unknown) => {
process.stderr.write(`[weixin] ${formatError(error)}\n`);
}) as any,
Expand Down
7 changes: 6 additions & 1 deletion src/runtime/weixin_bridge_runtime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ interface WeixinBridgeRuntimeOptions {
previewSoftTargetBytes?: number;
previewHardLimitBytes?: number;
previewIntervalMs?: number;
progressDeliveryEnabled?: boolean;
typingKeepaliveMs?: number;
inboundAttachmentMergeWindowMs?: number;
automationPollMs?: number;
Expand Down Expand Up @@ -175,6 +176,8 @@ export class WeixinBridgeRuntime {

previewIntervalMs: number;

progressDeliveryEnabled: boolean;

typingKeepaliveMs: number;

inboundAttachmentMergeWindowMs: number;
Expand Down Expand Up @@ -219,6 +222,7 @@ export class WeixinBridgeRuntime {
previewSoftTargetBytes = 2048,
previewHardLimitBytes = 2048,
previewIntervalMs = 3000,
progressDeliveryEnabled = true,
typingKeepaliveMs = WeixinBridgeRuntime.DEFAULT_TYPING_KEEPALIVE_MS,
inboundAttachmentMergeWindowMs = 3000,
automationPollMs = 30_000,
Expand All @@ -234,6 +238,7 @@ export class WeixinBridgeRuntime {
this.previewSoftTargetBytes = previewSoftTargetBytes;
this.previewHardLimitBytes = previewHardLimitBytes;
this.previewIntervalMs = previewIntervalMs;
this.progressDeliveryEnabled = progressDeliveryEnabled;
this.typingKeepaliveMs = typingKeepaliveMs;
this.inboundAttachmentMergeWindowMs = inboundAttachmentMergeWindowMs;
this.automationPollMs = automationPollMs;
Expand Down Expand Up @@ -534,7 +539,7 @@ export class WeixinBridgeRuntime {
try {
const response = await this.bridgeCoordinator.handleInboundEvent(event, {
onProgress: async (progress) => {
if (options.suppressProgressDelivery) {
if (options.suppressProgressDelivery || !this.progressDeliveryEnabled) {
return;
}
await this.handleProgressUpdate(event, streamState, progress);
Expand Down
35 changes: 35 additions & 0 deletions test/runtime/weixin_bridge_runtime.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ interface RuntimeHarnessOptions {
commitSyncCursor?: (syncCursor: string) => Promise<void> | void;
previewSoftTargetBytes?: number;
previewIntervalMs?: number;
progressDeliveryEnabled?: boolean;
typingKeepaliveMs?: number;
inboundAttachmentMergeWindowMs?: number;
automationPollMs?: number;
Expand All @@ -55,6 +56,7 @@ function makeRuntime({
commitSyncCursor,
previewSoftTargetBytes = 1,
previewIntervalMs = 0,
progressDeliveryEnabled = true,
typingKeepaliveMs = 8000,
inboundAttachmentMergeWindowMs = 3000,
automationPollMs = 30_000,
Expand Down Expand Up @@ -109,6 +111,7 @@ function makeRuntime({
assistantRecords,
previewSoftTargetBytes,
previewIntervalMs,
progressDeliveryEnabled,
typingKeepaliveMs,
inboundAttachmentMergeWindowMs,
automationPollMs,
Expand Down Expand Up @@ -1538,6 +1541,38 @@ test('WeixinBridgeRuntime merges commentary and final-answer progress into the p
]);
});

test('WeixinBridgeRuntime can disable Weixin progress preview delivery and send only the final response', async () => {
const sent: Array<{ externalScopeId: string; content: string }> = [];
const runtime = makeRuntime({
sendText: async ({ externalScopeId, content }) => {
sent.push({ externalScopeId, content });
},
progressDeliveryEnabled: false,
previewSoftTargetBytes: 1024,
coordinator: {
async handleInboundEvent(_event: any, options: any = {}) {
await options.onProgress?.({
text: '第一段预览。',
delta: '第一段预览。',
outputKind: 'commentary',
});
await options.onProgress?.({
text: '最终答案。',
delta: '最终答案。',
outputKind: 'final_answer',
});
return completeResponse('最终答案。');
},
},
});

await runtime.runOnce();

assert.deepEqual(sent, [
{ externalScopeId: 'wxid_1', content: '最终答案。' },
]);
});

test('WeixinBridgeRuntime dedupes overlapping cumulative final-answer updates in the preview stream', async () => {
const sent: Array<{ externalScopeId: string; content: string }> = [];
const runtime = makeRuntime({
Expand Down