@xgjktech/xg_cwork_im 1.12.9 → 1.14.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +18 -4
- package/dist/src/agent-context-types.d.ts +39 -1
- package/dist/src/agent-context-types.d.ts.map +1 -1
- package/dist/src/agent-context-types.js +52 -7
- package/dist/src/agent-context-types.js.map +1 -1
- package/dist/src/agent-context-types.test.d.ts +2 -0
- package/dist/src/agent-context-types.test.d.ts.map +1 -0
- package/dist/src/agent-context-types.test.js +61 -0
- package/dist/src/agent-context-types.test.js.map +1 -0
- package/dist/src/apply-sync-mapping.js +14 -6
- package/dist/src/apply-sync-mapping.js.map +1 -1
- package/dist/src/block-streaming-config.test.d.ts +2 -0
- package/dist/src/block-streaming-config.test.d.ts.map +1 -0
- package/dist/src/block-streaming-config.test.js +41 -0
- package/dist/src/block-streaming-config.test.js.map +1 -0
- package/dist/src/build-project-prompt.d.ts.map +1 -1
- package/dist/src/build-project-prompt.js +5 -1
- package/dist/src/build-project-prompt.js.map +1 -1
- package/dist/src/channel-config.d.ts +128 -0
- package/dist/src/channel-config.d.ts.map +1 -1
- package/dist/src/channel-config.js +67 -0
- package/dist/src/channel-config.js.map +1 -1
- package/dist/src/channel.d.ts.map +1 -1
- package/dist/src/channel.js +24 -8
- package/dist/src/channel.js.map +1 -1
- package/dist/src/connection.d.ts +7 -0
- package/dist/src/connection.d.ts.map +1 -1
- package/dist/src/connection.js +16 -1
- package/dist/src/connection.js.map +1 -1
- package/dist/src/deliver-text.d.ts +13 -0
- package/dist/src/deliver-text.d.ts.map +1 -0
- package/dist/src/deliver-text.js +28 -0
- package/dist/src/deliver-text.js.map +1 -0
- package/dist/src/deliver-text.test.d.ts +2 -0
- package/dist/src/deliver-text.test.d.ts.map +1 -0
- package/dist/src/deliver-text.test.js +31 -0
- package/dist/src/deliver-text.test.js.map +1 -0
- package/dist/src/dispatch-mentioned-reply.d.ts +3 -0
- package/dist/src/dispatch-mentioned-reply.d.ts.map +1 -1
- package/dist/src/dispatch-mentioned-reply.js +124 -76
- package/dist/src/dispatch-mentioned-reply.js.map +1 -1
- package/dist/src/gateway-session-queue.d.ts +3 -0
- package/dist/src/gateway-session-queue.d.ts.map +1 -1
- package/dist/src/gateway-session-queue.js +1 -0
- package/dist/src/gateway-session-queue.js.map +1 -1
- package/dist/src/inbound-chat-type.d.ts +4 -0
- package/dist/src/inbound-chat-type.d.ts.map +1 -1
- package/dist/src/inbound-chat-type.js +8 -0
- package/dist/src/inbound-chat-type.js.map +1 -1
- package/dist/src/inbound-display.d.ts +2 -0
- package/dist/src/inbound-display.d.ts.map +1 -1
- package/dist/src/inbound-display.js +16 -5
- package/dist/src/inbound-display.js.map +1 -1
- package/dist/src/inbound-input-media.js +1 -1
- package/dist/src/inbound-input-media.js.map +1 -1
- package/dist/src/inbound-media-local.js +1 -1
- package/dist/src/inbound-media-local.js.map +1 -1
- package/dist/src/inbound-terminal-delivery.d.ts +74 -0
- package/dist/src/inbound-terminal-delivery.d.ts.map +1 -0
- package/dist/src/inbound-terminal-delivery.js +246 -0
- package/dist/src/inbound-terminal-delivery.js.map +1 -0
- package/dist/src/inbound-terminal-state.d.ts +61 -0
- package/dist/src/inbound-terminal-state.d.ts.map +1 -0
- package/dist/src/inbound-terminal-state.js +177 -0
- package/dist/src/inbound-terminal-state.js.map +1 -0
- package/dist/src/inbound-terminal-state.test.d.ts +2 -0
- package/dist/src/inbound-terminal-state.test.d.ts.map +1 -0
- package/dist/src/inbound-terminal-state.test.js +203 -0
- package/dist/src/inbound-terminal-state.test.js.map +1 -0
- package/dist/src/per-message-fallback-notice.d.ts +11 -1
- package/dist/src/per-message-fallback-notice.d.ts.map +1 -1
- package/dist/src/per-message-fallback-notice.js +16 -1
- package/dist/src/per-message-fallback-notice.js.map +1 -1
- package/dist/src/per-message-fallback-notice.test.d.ts +2 -0
- package/dist/src/per-message-fallback-notice.test.d.ts.map +1 -0
- package/dist/src/per-message-fallback-notice.test.js +47 -0
- package/dist/src/per-message-fallback-notice.test.js.map +1 -0
- package/dist/src/project-path-normalize.d.ts +14 -0
- package/dist/src/project-path-normalize.d.ts.map +1 -1
- package/dist/src/project-path-normalize.js +26 -0
- package/dist/src/project-path-normalize.js.map +1 -1
- package/dist/src/resource-file.d.ts +7 -1
- package/dist/src/resource-file.d.ts.map +1 -1
- package/dist/src/resource-file.js +56 -19
- package/dist/src/resource-file.js.map +1 -1
- package/dist/src/send-group-message-tool.d.ts.map +1 -1
- package/dist/src/send-group-message-tool.js +4 -2
- package/dist/src/send-group-message-tool.js.map +1 -1
- package/dist/src/send-service.d.ts.map +1 -1
- package/dist/src/send-service.js +33 -7
- package/dist/src/send-service.js.map +1 -1
- package/dist/src/sync-mapping-types.d.ts +58 -8
- package/dist/src/sync-mapping-types.d.ts.map +1 -1
- package/dist/src/sync-mapping-types.js +19 -5
- package/dist/src/sync-mapping-types.js.map +1 -1
- package/dist/src/sync-service-client.d.ts +3 -1
- package/dist/src/sync-service-client.d.ts.map +1 -1
- package/dist/src/sync-service-client.js.map +1 -1
- package/dist/src/types.d.ts +27 -0
- package/dist/src/types.d.ts.map +1 -1
- package/dist/src/types.js.map +1 -1
- package/package.json +3 -2
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* IM 入站消息终态:分类、用户可见文案、结构化日志字段。
|
|
3
|
+
*/
|
|
4
|
+
export type InboundTrigger = "user" | "cron" | "tool" | "heartbeat" | "system" | "runtime_continue";
|
|
5
|
+
export type TerminalState = "success" | "no_reply" | "timeout" | "runtime_error" | "precheck_error" | "compaction_failed" | "delivery_failed" | "cancelled" | "superseded";
|
|
6
|
+
export type RuntimeErrorHint = {
|
|
7
|
+
errorType: TerminalState;
|
|
8
|
+
errorMessage: string;
|
|
9
|
+
};
|
|
10
|
+
export declare function classifyRuntimeErrorMessage(message: string): RuntimeErrorHint;
|
|
11
|
+
export declare function classifyRuntimeError(err: unknown): RuntimeErrorHint;
|
|
12
|
+
export declare function buildTerminalUserMessage(state: TerminalState): string;
|
|
13
|
+
export type TerminalLogFields = {
|
|
14
|
+
message_id: string;
|
|
15
|
+
group_id: string;
|
|
16
|
+
session_key: string;
|
|
17
|
+
run_id?: string;
|
|
18
|
+
trigger: InboundTrigger;
|
|
19
|
+
terminal_state: TerminalState;
|
|
20
|
+
sent_to_im: boolean;
|
|
21
|
+
error_type?: TerminalState;
|
|
22
|
+
error_message?: string;
|
|
23
|
+
no_reply_cause?: NoReplyCause;
|
|
24
|
+
deliver_invoke_count?: number;
|
|
25
|
+
deliver_call_count?: number;
|
|
26
|
+
normalizer_silent_skip?: boolean;
|
|
27
|
+
normalizer_heartbeat_skip?: boolean;
|
|
28
|
+
http_suppressed_reason?: "intentional_silent" | "heartbeat_only";
|
|
29
|
+
};
|
|
30
|
+
export declare function formatTerminalLogLine(fields: TerminalLogFields): string;
|
|
31
|
+
/** 终态为 no_reply 时的细分原因(用于日志与是否发 HTTP 兜底)。 */
|
|
32
|
+
export type NoReplyCause = "intentional_silent" | "heartbeat_only" | "zero_deliver" | "all_deliver_skipped" | "unknown";
|
|
33
|
+
export type ResolveTerminalStateInput = {
|
|
34
|
+
hasBusinessReply: boolean;
|
|
35
|
+
timeoutFired: boolean;
|
|
36
|
+
dispatchThrew: boolean;
|
|
37
|
+
dispatchError?: unknown;
|
|
38
|
+
lastDeliverError?: unknown;
|
|
39
|
+
beforeAgentRunBlocked?: boolean;
|
|
40
|
+
compactionShown: boolean;
|
|
41
|
+
compactionIncomplete: boolean;
|
|
42
|
+
runtimeErrorHint?: RuntimeErrorHint;
|
|
43
|
+
deliverInvokeCount: number;
|
|
44
|
+
deliverCallCount: number;
|
|
45
|
+
/** OpenClaw normalizer 因 NO_REPLY / silent token 跳过 payload(onSkip reason=silent) */
|
|
46
|
+
normalizerSilentSkip?: boolean;
|
|
47
|
+
/** normalizer 因 HEARTBEAT_OK 等跳过(onSkip reason=heartbeat) */
|
|
48
|
+
normalizerHeartbeatSkip?: boolean;
|
|
49
|
+
};
|
|
50
|
+
export declare function resolveHttpSuppressedReason(state: TerminalState, input: Pick<ResolveTerminalStateInput, "normalizerSilentSkip" | "normalizerHeartbeatSkip">): "intentional_silent" | "heartbeat_only" | undefined;
|
|
51
|
+
/** 模型/OpenClaw 主动静默(NO_REPLY、heartbeat)时不应向 IM 发「没有生成回复」HTTP。 */
|
|
52
|
+
export declare function shouldSendTerminalHttpForState(state: TerminalState, input: Pick<ResolveTerminalStateInput, "normalizerSilentSkip" | "normalizerHeartbeatSkip">): boolean;
|
|
53
|
+
export declare function resolveNoReplyCause(input: ResolveTerminalStateInput): NoReplyCause | undefined;
|
|
54
|
+
/** 在 finally 阶段根据观测信号推断终态(success 由 hasBusinessReply 在外层短路)。 */
|
|
55
|
+
export declare function resolveTerminalState(input: ResolveTerminalStateInput): TerminalState;
|
|
56
|
+
export declare function hasGlobalTerminalSent(messageId: string): boolean;
|
|
57
|
+
export declare function markGlobalTerminalSent(messageId: string, state: TerminalState): void;
|
|
58
|
+
export declare function peekGlobalTerminalSent(messageId: string): TerminalState | undefined;
|
|
59
|
+
/** 测试用:清空进程级幂等表。 */
|
|
60
|
+
export declare function resetGlobalTerminalSentForTests(): void;
|
|
61
|
+
//# sourceMappingURL=inbound-terminal-state.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inbound-terminal-state.d.ts","sourceRoot":"","sources":["../../src/inbound-terminal-state.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* IM 入站消息终态:分类、用户可见文案、结构化日志字段。
|
|
3
|
+
*/
|
|
4
|
+
const PRECHECK_MARKERS = [
|
|
5
|
+
"context overflow",
|
|
6
|
+
"prompt too large",
|
|
7
|
+
"precheck",
|
|
8
|
+
"too large for the model",
|
|
9
|
+
"too large for this model",
|
|
10
|
+
];
|
|
11
|
+
const TIMEOUT_MARKERS = ["request timed out", "timed out", "idle timeout", "llm idle timeout"];
|
|
12
|
+
const NO_REPLY_MARKERS = ["no_reply", "no reply"];
|
|
13
|
+
export function classifyRuntimeErrorMessage(message) {
|
|
14
|
+
const raw = message.trim();
|
|
15
|
+
const lower = raw.toLowerCase();
|
|
16
|
+
if (PRECHECK_MARKERS.some((m) => lower.includes(m))) {
|
|
17
|
+
return { errorType: "precheck_error", errorMessage: raw };
|
|
18
|
+
}
|
|
19
|
+
if (TIMEOUT_MARKERS.some((m) => lower.includes(m))) {
|
|
20
|
+
return { errorType: "timeout", errorMessage: raw };
|
|
21
|
+
}
|
|
22
|
+
if (NO_REPLY_MARKERS.some((m) => lower.includes(m))) {
|
|
23
|
+
return { errorType: "no_reply", errorMessage: raw };
|
|
24
|
+
}
|
|
25
|
+
if (lower.includes("compaction") && (lower.includes("incomplete") || lower.includes("failed"))) {
|
|
26
|
+
return { errorType: "compaction_failed", errorMessage: raw };
|
|
27
|
+
}
|
|
28
|
+
return { errorType: "runtime_error", errorMessage: raw };
|
|
29
|
+
}
|
|
30
|
+
export function classifyRuntimeError(err) {
|
|
31
|
+
if (err instanceof Error) {
|
|
32
|
+
return classifyRuntimeErrorMessage(err.message);
|
|
33
|
+
}
|
|
34
|
+
return classifyRuntimeErrorMessage(String(err));
|
|
35
|
+
}
|
|
36
|
+
export function buildTerminalUserMessage(state) {
|
|
37
|
+
switch (state) {
|
|
38
|
+
case "precheck_error":
|
|
39
|
+
return ("当前上下文过大,本轮未能启动模型调用。系统已记录,请稍后重试或等待上下文压缩完成。");
|
|
40
|
+
case "compaction_failed":
|
|
41
|
+
return "上下文压缩后仍未生成回复,请精简对话历史或新开话题后再试。";
|
|
42
|
+
case "timeout":
|
|
43
|
+
return "当前请求处理超时,请稍后重试。";
|
|
44
|
+
case "no_reply":
|
|
45
|
+
return "消息已收到,但这一轮没有生成回复。请换个说法或把需求说具体一些后再试。";
|
|
46
|
+
case "runtime_error":
|
|
47
|
+
return "当前请求处理时出现异常,请稍后重试。";
|
|
48
|
+
case "delivery_failed":
|
|
49
|
+
return "回复已生成但发送到 IM 失败,请稍后重试。";
|
|
50
|
+
case "cancelled":
|
|
51
|
+
return "当前请求已取消。";
|
|
52
|
+
case "superseded":
|
|
53
|
+
return "当前请求已被更新的处理覆盖。";
|
|
54
|
+
case "success":
|
|
55
|
+
return "";
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
export function formatTerminalLogLine(fields) {
|
|
59
|
+
const parts = [
|
|
60
|
+
`[terminal] message_id=${fields.message_id}`,
|
|
61
|
+
`group_id=${fields.group_id}`,
|
|
62
|
+
`session_key=${fields.session_key}`,
|
|
63
|
+
fields.run_id ? `run_id=${fields.run_id}` : undefined,
|
|
64
|
+
`trigger=${fields.trigger}`,
|
|
65
|
+
`terminal_state=${fields.terminal_state}`,
|
|
66
|
+
`sent_to_im=${fields.sent_to_im}`,
|
|
67
|
+
fields.error_type ? `error_type=${fields.error_type}` : undefined,
|
|
68
|
+
fields.error_message ? `error_message=${JSON.stringify(fields.error_message)}` : undefined,
|
|
69
|
+
fields.no_reply_cause ? `no_reply_cause=${fields.no_reply_cause}` : undefined,
|
|
70
|
+
fields.deliver_invoke_count != null ? `deliver_invoke_count=${fields.deliver_invoke_count}` : undefined,
|
|
71
|
+
fields.deliver_call_count != null ? `deliver_call_count=${fields.deliver_call_count}` : undefined,
|
|
72
|
+
fields.normalizer_silent_skip != null
|
|
73
|
+
? `normalizer_silent_skip=${fields.normalizer_silent_skip}`
|
|
74
|
+
: undefined,
|
|
75
|
+
fields.normalizer_heartbeat_skip != null
|
|
76
|
+
? `normalizer_heartbeat_skip=${fields.normalizer_heartbeat_skip}`
|
|
77
|
+
: undefined,
|
|
78
|
+
fields.http_suppressed_reason ? `http_suppressed_reason=${fields.http_suppressed_reason}` : undefined,
|
|
79
|
+
].filter(Boolean);
|
|
80
|
+
return parts.join(" ");
|
|
81
|
+
}
|
|
82
|
+
export function resolveHttpSuppressedReason(state, input) {
|
|
83
|
+
if (state !== "no_reply") {
|
|
84
|
+
return undefined;
|
|
85
|
+
}
|
|
86
|
+
if (input.normalizerSilentSkip) {
|
|
87
|
+
return "intentional_silent";
|
|
88
|
+
}
|
|
89
|
+
if (input.normalizerHeartbeatSkip) {
|
|
90
|
+
return "heartbeat_only";
|
|
91
|
+
}
|
|
92
|
+
return undefined;
|
|
93
|
+
}
|
|
94
|
+
/** 模型/OpenClaw 主动静默(NO_REPLY、heartbeat)时不应向 IM 发「没有生成回复」HTTP。 */
|
|
95
|
+
export function shouldSendTerminalHttpForState(state, input) {
|
|
96
|
+
if (state !== "no_reply") {
|
|
97
|
+
return true;
|
|
98
|
+
}
|
|
99
|
+
if (input.normalizerSilentSkip || input.normalizerHeartbeatSkip) {
|
|
100
|
+
return false;
|
|
101
|
+
}
|
|
102
|
+
return true;
|
|
103
|
+
}
|
|
104
|
+
export function resolveNoReplyCause(input) {
|
|
105
|
+
if (input.hasBusinessReply) {
|
|
106
|
+
return undefined;
|
|
107
|
+
}
|
|
108
|
+
if (input.normalizerSilentSkip) {
|
|
109
|
+
return "intentional_silent";
|
|
110
|
+
}
|
|
111
|
+
if (input.normalizerHeartbeatSkip) {
|
|
112
|
+
return "heartbeat_only";
|
|
113
|
+
}
|
|
114
|
+
if (input.deliverInvokeCount === 0) {
|
|
115
|
+
return "zero_deliver";
|
|
116
|
+
}
|
|
117
|
+
if (input.deliverInvokeCount > 0 && input.deliverCallCount === 0) {
|
|
118
|
+
return "all_deliver_skipped";
|
|
119
|
+
}
|
|
120
|
+
return "unknown";
|
|
121
|
+
}
|
|
122
|
+
/** 在 finally 阶段根据观测信号推断终态(success 由 hasBusinessReply 在外层短路)。 */
|
|
123
|
+
export function resolveTerminalState(input) {
|
|
124
|
+
if (input.hasBusinessReply) {
|
|
125
|
+
return "success";
|
|
126
|
+
}
|
|
127
|
+
if (input.timeoutFired) {
|
|
128
|
+
return "timeout";
|
|
129
|
+
}
|
|
130
|
+
if (input.lastDeliverError !== undefined) {
|
|
131
|
+
return "delivery_failed";
|
|
132
|
+
}
|
|
133
|
+
if (input.runtimeErrorHint) {
|
|
134
|
+
return input.runtimeErrorHint.errorType;
|
|
135
|
+
}
|
|
136
|
+
if (input.dispatchError !== undefined) {
|
|
137
|
+
return classifyRuntimeError(input.dispatchError).errorType;
|
|
138
|
+
}
|
|
139
|
+
if (input.beforeAgentRunBlocked) {
|
|
140
|
+
return "precheck_error";
|
|
141
|
+
}
|
|
142
|
+
if (input.compactionIncomplete || (input.compactionShown && input.deliverCallCount === 0)) {
|
|
143
|
+
return "compaction_failed";
|
|
144
|
+
}
|
|
145
|
+
if (input.deliverInvokeCount > 0 &&
|
|
146
|
+
input.deliverCallCount === 0 &&
|
|
147
|
+
input.runtimeErrorHint === undefined &&
|
|
148
|
+
input.dispatchError === undefined &&
|
|
149
|
+
input.lastDeliverError === undefined) {
|
|
150
|
+
return "no_reply";
|
|
151
|
+
}
|
|
152
|
+
if (input.deliverInvokeCount === 0 && !input.dispatchThrew) {
|
|
153
|
+
return "no_reply";
|
|
154
|
+
}
|
|
155
|
+
return "runtime_error";
|
|
156
|
+
}
|
|
157
|
+
/** 进程级幂等:同一 message_id 终态 HTTP 最多发一次。 */
|
|
158
|
+
const globalTerminalSent = new Map();
|
|
159
|
+
export function hasGlobalTerminalSent(messageId) {
|
|
160
|
+
return globalTerminalSent.has(messageId.trim());
|
|
161
|
+
}
|
|
162
|
+
export function markGlobalTerminalSent(messageId, state) {
|
|
163
|
+
const id = messageId.trim();
|
|
164
|
+
if (!id)
|
|
165
|
+
return;
|
|
166
|
+
if (!globalTerminalSent.has(id)) {
|
|
167
|
+
globalTerminalSent.set(id, state);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
export function peekGlobalTerminalSent(messageId) {
|
|
171
|
+
return globalTerminalSent.get(messageId.trim());
|
|
172
|
+
}
|
|
173
|
+
/** 测试用:清空进程级幂等表。 */
|
|
174
|
+
export function resetGlobalTerminalSentForTests() {
|
|
175
|
+
globalTerminalSent.clear();
|
|
176
|
+
}
|
|
177
|
+
//# sourceMappingURL=inbound-terminal-state.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inbound-terminal-state.js","sourceRoot":"","sources":["../../src/inbound-terminal-state.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inbound-terminal-state.test.d.ts","sourceRoot":"","sources":["../../src/inbound-terminal-state.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import { describe, it, beforeEach } from "node:test";
|
|
3
|
+
import { buildTerminalUserMessage, classifyRuntimeErrorMessage, hasGlobalTerminalSent, markGlobalTerminalSent, resetGlobalTerminalSentForTests, resolveNoReplyCause, resolveTerminalState, shouldSendTerminalHttpForState, } from "./inbound-terminal-state.js";
|
|
4
|
+
import { InboundTerminalController, prefixProactiveOutboundText } from "./inbound-terminal-delivery.js";
|
|
5
|
+
describe("classifyRuntimeErrorMessage", () => {
|
|
6
|
+
it("detects precheck overflow", () => {
|
|
7
|
+
const hint = classifyRuntimeErrorMessage("Context overflow: prompt too large for the model (precheck)");
|
|
8
|
+
assert.equal(hint.errorType, "precheck_error");
|
|
9
|
+
});
|
|
10
|
+
it("detects timeout", () => {
|
|
11
|
+
const hint = classifyRuntimeErrorMessage("Request timed out.");
|
|
12
|
+
assert.equal(hint.errorType, "timeout");
|
|
13
|
+
});
|
|
14
|
+
it("detects no_reply", () => {
|
|
15
|
+
const hint = classifyRuntimeErrorMessage("NO_REPLY");
|
|
16
|
+
assert.equal(hint.errorType, "no_reply");
|
|
17
|
+
});
|
|
18
|
+
});
|
|
19
|
+
describe("resolveTerminalState", () => {
|
|
20
|
+
it("returns success when business reply sent", () => {
|
|
21
|
+
assert.equal(resolveTerminalState({
|
|
22
|
+
hasBusinessReply: true,
|
|
23
|
+
timeoutFired: false,
|
|
24
|
+
dispatchThrew: false,
|
|
25
|
+
compactionShown: false,
|
|
26
|
+
compactionIncomplete: false,
|
|
27
|
+
deliverInvokeCount: 1,
|
|
28
|
+
deliverCallCount: 1,
|
|
29
|
+
}), "success");
|
|
30
|
+
});
|
|
31
|
+
it("returns precheck_error from runtime hint", () => {
|
|
32
|
+
assert.equal(resolveTerminalState({
|
|
33
|
+
hasBusinessReply: false,
|
|
34
|
+
timeoutFired: false,
|
|
35
|
+
dispatchThrew: false,
|
|
36
|
+
compactionShown: false,
|
|
37
|
+
compactionIncomplete: false,
|
|
38
|
+
deliverInvokeCount: 1,
|
|
39
|
+
deliverCallCount: 0,
|
|
40
|
+
runtimeErrorHint: {
|
|
41
|
+
errorType: "precheck_error",
|
|
42
|
+
errorMessage: "Context overflow: prompt too large for the model (precheck)",
|
|
43
|
+
},
|
|
44
|
+
}), "precheck_error");
|
|
45
|
+
});
|
|
46
|
+
it("returns compaction_failed when compaction shown without reply", () => {
|
|
47
|
+
assert.equal(resolveTerminalState({
|
|
48
|
+
hasBusinessReply: false,
|
|
49
|
+
timeoutFired: false,
|
|
50
|
+
dispatchThrew: false,
|
|
51
|
+
compactionShown: true,
|
|
52
|
+
compactionIncomplete: false,
|
|
53
|
+
deliverInvokeCount: 0,
|
|
54
|
+
deliverCallCount: 0,
|
|
55
|
+
}), "compaction_failed");
|
|
56
|
+
});
|
|
57
|
+
it("returns no_reply when deliver invoked but all plugin-skipped", () => {
|
|
58
|
+
assert.equal(resolveTerminalState({
|
|
59
|
+
hasBusinessReply: false,
|
|
60
|
+
timeoutFired: false,
|
|
61
|
+
dispatchThrew: false,
|
|
62
|
+
compactionShown: false,
|
|
63
|
+
compactionIncomplete: false,
|
|
64
|
+
deliverInvokeCount: 3,
|
|
65
|
+
deliverCallCount: 0,
|
|
66
|
+
}), "no_reply");
|
|
67
|
+
});
|
|
68
|
+
it("returns no_reply for silent turn without deliver", () => {
|
|
69
|
+
assert.equal(resolveTerminalState({
|
|
70
|
+
hasBusinessReply: false,
|
|
71
|
+
timeoutFired: false,
|
|
72
|
+
dispatchThrew: false,
|
|
73
|
+
compactionShown: false,
|
|
74
|
+
compactionIncomplete: false,
|
|
75
|
+
deliverInvokeCount: 0,
|
|
76
|
+
deliverCallCount: 0,
|
|
77
|
+
}), "no_reply");
|
|
78
|
+
});
|
|
79
|
+
it("returns timeout when watchdog fired", () => {
|
|
80
|
+
assert.equal(resolveTerminalState({
|
|
81
|
+
hasBusinessReply: false,
|
|
82
|
+
timeoutFired: true,
|
|
83
|
+
dispatchThrew: false,
|
|
84
|
+
compactionShown: false,
|
|
85
|
+
compactionIncomplete: false,
|
|
86
|
+
deliverInvokeCount: 0,
|
|
87
|
+
deliverCallCount: 0,
|
|
88
|
+
}), "timeout");
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
describe("shouldSendTerminalHttpForState", () => {
|
|
92
|
+
it("suppresses HTTP for intentional NO_REPLY silent skip", () => {
|
|
93
|
+
assert.equal(shouldSendTerminalHttpForState("no_reply", { normalizerSilentSkip: true }), false);
|
|
94
|
+
});
|
|
95
|
+
it("keeps HTTP for genuine empty deliver", () => {
|
|
96
|
+
assert.equal(shouldSendTerminalHttpForState("no_reply", {
|
|
97
|
+
normalizerSilentSkip: false,
|
|
98
|
+
normalizerHeartbeatSkip: false,
|
|
99
|
+
}), true);
|
|
100
|
+
});
|
|
101
|
+
});
|
|
102
|
+
describe("resolveNoReplyCause", () => {
|
|
103
|
+
it("classifies intentional silent", () => {
|
|
104
|
+
assert.equal(resolveNoReplyCause({
|
|
105
|
+
hasBusinessReply: false,
|
|
106
|
+
timeoutFired: false,
|
|
107
|
+
dispatchThrew: false,
|
|
108
|
+
compactionShown: false,
|
|
109
|
+
compactionIncomplete: false,
|
|
110
|
+
deliverInvokeCount: 0,
|
|
111
|
+
deliverCallCount: 0,
|
|
112
|
+
normalizerSilentSkip: true,
|
|
113
|
+
}), "intentional_silent");
|
|
114
|
+
});
|
|
115
|
+
});
|
|
116
|
+
describe("buildTerminalUserMessage", () => {
|
|
117
|
+
it("uses distinct copy for precheck vs no_reply", () => {
|
|
118
|
+
const precheck = buildTerminalUserMessage("precheck_error");
|
|
119
|
+
const noReply = buildTerminalUserMessage("no_reply");
|
|
120
|
+
assert.ok(precheck.includes("上下文过大"));
|
|
121
|
+
assert.ok(noReply.includes("没有生成回复"));
|
|
122
|
+
assert.notEqual(precheck, noReply);
|
|
123
|
+
});
|
|
124
|
+
});
|
|
125
|
+
describe("InboundTerminalController idempotency", () => {
|
|
126
|
+
const noopLog = {
|
|
127
|
+
info: () => { },
|
|
128
|
+
warn: () => { },
|
|
129
|
+
error: () => { },
|
|
130
|
+
};
|
|
131
|
+
beforeEach(() => {
|
|
132
|
+
resetGlobalTerminalSentForTests();
|
|
133
|
+
});
|
|
134
|
+
it("sends terminal only once per message_id", async () => {
|
|
135
|
+
const controller = new InboundTerminalController({
|
|
136
|
+
messageId: "msg-1001",
|
|
137
|
+
groupId: "g1",
|
|
138
|
+
sessionKey: "sk1",
|
|
139
|
+
log: noopLog,
|
|
140
|
+
logPrefix: "[test]",
|
|
141
|
+
});
|
|
142
|
+
let sendCount = 0;
|
|
143
|
+
const sendFn = async () => {
|
|
144
|
+
sendCount++;
|
|
145
|
+
};
|
|
146
|
+
const first = await controller.trySendTerminal("precheck_error", sendFn);
|
|
147
|
+
const second = await controller.trySendTerminal("precheck_error", sendFn);
|
|
148
|
+
assert.equal(first, true);
|
|
149
|
+
assert.equal(second, false);
|
|
150
|
+
assert.equal(sendCount, 1);
|
|
151
|
+
assert.equal(hasGlobalTerminalSent("msg-1001"), true);
|
|
152
|
+
});
|
|
153
|
+
it("finalize delivers precheck when error payload was noted", async () => {
|
|
154
|
+
const controller = new InboundTerminalController({
|
|
155
|
+
messageId: "msg-2002",
|
|
156
|
+
groupId: "g2",
|
|
157
|
+
sessionKey: "sk2",
|
|
158
|
+
log: noopLog,
|
|
159
|
+
logPrefix: "[test]",
|
|
160
|
+
});
|
|
161
|
+
controller.noteRuntimeErrorFromPayload("Context overflow: prompt too large for the model (precheck)");
|
|
162
|
+
let sent = "";
|
|
163
|
+
const state = await controller.finalizeAndDeliver({
|
|
164
|
+
sendFn: async (text) => {
|
|
165
|
+
sent = text;
|
|
166
|
+
},
|
|
167
|
+
dispatchThrew: false,
|
|
168
|
+
deliverInvokeCount: 1,
|
|
169
|
+
deliverCallCount: 0,
|
|
170
|
+
});
|
|
171
|
+
assert.equal(state, "precheck_error");
|
|
172
|
+
assert.ok(sent.includes("上下文过大"));
|
|
173
|
+
markGlobalTerminalSent("msg-2002", "precheck_error");
|
|
174
|
+
});
|
|
175
|
+
it("does not send HTTP for intentional NO_REPLY silent skip", async () => {
|
|
176
|
+
const controller = new InboundTerminalController({
|
|
177
|
+
messageId: "msg-3003",
|
|
178
|
+
groupId: "g3",
|
|
179
|
+
sessionKey: "sk3",
|
|
180
|
+
log: noopLog,
|
|
181
|
+
logPrefix: "[test]",
|
|
182
|
+
});
|
|
183
|
+
controller.noteNormalizerSkip("silent");
|
|
184
|
+
let sendCount = 0;
|
|
185
|
+
const state = await controller.finalizeAndDeliver({
|
|
186
|
+
sendFn: async () => {
|
|
187
|
+
sendCount++;
|
|
188
|
+
},
|
|
189
|
+
dispatchThrew: false,
|
|
190
|
+
deliverInvokeCount: 0,
|
|
191
|
+
deliverCallCount: 0,
|
|
192
|
+
});
|
|
193
|
+
assert.equal(state, "no_reply");
|
|
194
|
+
assert.equal(sendCount, 0);
|
|
195
|
+
});
|
|
196
|
+
});
|
|
197
|
+
describe("prefixProactiveOutboundText", () => {
|
|
198
|
+
it("prefixes cron messages once", () => {
|
|
199
|
+
assert.equal(prefixProactiveOutboundText("今日无新增"), "[定时任务] 今日无新增");
|
|
200
|
+
assert.equal(prefixProactiveOutboundText("[定时任务] 已有"), "[定时任务] 已有");
|
|
201
|
+
});
|
|
202
|
+
});
|
|
203
|
+
//# sourceMappingURL=inbound-terminal-state.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inbound-terminal-state.test.js","sourceRoot":"","sources":["../../src/inbound-terminal-state.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -20,7 +20,7 @@ export declare function normalizeModelRefString(raw: string): string;
|
|
|
20
20
|
export declare function parseFallbackNoticeEffectiveModelRef(noticeText: string): string | undefined;
|
|
21
21
|
export declare function runtimeModelRefsMatch(requestedRaw: string | undefined, actualKey: string | undefined): boolean;
|
|
22
22
|
/**
|
|
23
|
-
* 是否应抑制发往 IM 的 fallback
|
|
23
|
+
* 是否应抑制发往 IM 的 fallback 运营通知(在通道已开启投递时的细粒度规则)。
|
|
24
24
|
* - 无 ai_model:不抑制
|
|
25
25
|
* - 有 ai_model 且通知中的实际模型与指定一致:抑制(误报)
|
|
26
26
|
* - 有 ai_model 但实际模型不同:不抑制(真实 failover)
|
|
@@ -30,4 +30,14 @@ export declare function shouldSuppressPerMessageFallbackNotice(params: {
|
|
|
30
30
|
requestedModelRaw: string | undefined;
|
|
31
31
|
noticeText?: string;
|
|
32
32
|
}): boolean;
|
|
33
|
+
/**
|
|
34
|
+
* IM deliver 是否应抑制 fallback 运营通知。
|
|
35
|
+
* 默认不投递;仅 `deliverModelFallbackNotice: true` 时考虑下发,并仍过滤 ai_model 误报。
|
|
36
|
+
*/
|
|
37
|
+
export declare function shouldSuppressFallbackNoticeForIm(params: {
|
|
38
|
+
isFallbackNotice: boolean;
|
|
39
|
+
deliverModelFallbackNotice?: boolean;
|
|
40
|
+
requestedModelRaw?: string;
|
|
41
|
+
noticeText?: string;
|
|
42
|
+
}): boolean;
|
|
33
43
|
//# sourceMappingURL=per-message-fallback-notice.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"per-message-fallback-notice.d.ts","sourceRoot":"","sources":["../../src/per-message-fallback-notice.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,MAAM,MAAM,eAAe,GAAG;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAElE,uDAAuD;AACvD,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAKhF;AAED,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAI3D;AAUD;;;;GAIG;AACH,wBAAgB,oCAAoC,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAO3F;AAED,wBAAgB,qBAAqB,CACjC,YAAY,EAAE,MAAM,GAAG,SAAS,EAChC,SAAS,EAAE,MAAM,GAAG,SAAS,GAC9B,OAAO,CAQT;AAED;;;;;GAKG;AACH,wBAAgB,sCAAsC,CAAC,MAAM,EAAE;IAC3D,gBAAgB,EAAE,OAAO,CAAC;IAC1B,iBAAiB,EAAE,MAAM,GAAG,SAAS,CAAC;IACtC,UAAU,CAAC,EAAE,MAAM,CAAC;CACvB,GAAG,OAAO,CAQV"}
|
|
1
|
+
{"version":3,"file":"per-message-fallback-notice.d.ts","sourceRoot":"","sources":["../../src/per-message-fallback-notice.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,MAAM,MAAM,eAAe,GAAG;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAElE,uDAAuD;AACvD,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAKhF;AAED,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAI3D;AAUD;;;;GAIG;AACH,wBAAgB,oCAAoC,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAO3F;AAED,wBAAgB,qBAAqB,CACjC,YAAY,EAAE,MAAM,GAAG,SAAS,EAChC,SAAS,EAAE,MAAM,GAAG,SAAS,GAC9B,OAAO,CAQT;AAED;;;;;GAKG;AACH,wBAAgB,sCAAsC,CAAC,MAAM,EAAE;IAC3D,gBAAgB,EAAE,OAAO,CAAC;IAC1B,iBAAiB,EAAE,MAAM,GAAG,SAAS,CAAC;IACtC,UAAU,CAAC,EAAE,MAAM,CAAC;CACvB,GAAG,OAAO,CAQV;AAED;;;GAGG;AACH,wBAAgB,iCAAiC,CAAC,MAAM,EAAE;IACtD,gBAAgB,EAAE,OAAO,CAAC;IAC1B,0BAA0B,CAAC,EAAE,OAAO,CAAC;IACrC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,UAAU,CAAC,EAAE,MAAM,CAAC;CACvB,GAAG,OAAO,CAQV"}
|
|
@@ -58,7 +58,7 @@ export function runtimeModelRefsMatch(requestedRaw, actualKey) {
|
|
|
58
58
|
return false;
|
|
59
59
|
}
|
|
60
60
|
/**
|
|
61
|
-
* 是否应抑制发往 IM 的 fallback
|
|
61
|
+
* 是否应抑制发往 IM 的 fallback 运营通知(在通道已开启投递时的细粒度规则)。
|
|
62
62
|
* - 无 ai_model:不抑制
|
|
63
63
|
* - 有 ai_model 且通知中的实际模型与指定一致:抑制(误报)
|
|
64
64
|
* - 有 ai_model 但实际模型不同:不抑制(真实 failover)
|
|
@@ -75,4 +75,19 @@ export function shouldSuppressPerMessageFallbackNotice(params) {
|
|
|
75
75
|
return false;
|
|
76
76
|
return runtimeModelRefsMatch(params.requestedModelRaw, effectiveFromNotice);
|
|
77
77
|
}
|
|
78
|
+
/**
|
|
79
|
+
* IM deliver 是否应抑制 fallback 运营通知。
|
|
80
|
+
* 默认不投递;仅 `deliverModelFallbackNotice: true` 时考虑下发,并仍过滤 ai_model 误报。
|
|
81
|
+
*/
|
|
82
|
+
export function shouldSuppressFallbackNoticeForIm(params) {
|
|
83
|
+
if (!params.isFallbackNotice)
|
|
84
|
+
return false;
|
|
85
|
+
if (params.deliverModelFallbackNotice !== true)
|
|
86
|
+
return true;
|
|
87
|
+
return shouldSuppressPerMessageFallbackNotice({
|
|
88
|
+
isFallbackNotice: true,
|
|
89
|
+
requestedModelRaw: params.requestedModelRaw,
|
|
90
|
+
noticeText: params.noticeText,
|
|
91
|
+
});
|
|
92
|
+
}
|
|
78
93
|
//# sourceMappingURL=per-message-fallback-notice.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"per-message-fallback-notice.js","sourceRoot":"","sources":["../../src/per-message-fallback-notice.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"per-message-fallback-notice.js","sourceRoot":"","sources":["../../src/per-message-fallback-notice.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAC;AAI/D,uDAAuD;AACvD,MAAM,UAAU,wBAAwB,CAAC,QAAgB,EAAE,KAAa;IACpE,MAAM,CAAC,GAAG,QAAQ,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IACxC,MAAM,CAAC,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IACrC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC;QAAE,OAAO,EAAE,CAAC;IACxB,OAAO,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;AACvB,CAAC;AAED,MAAM,UAAU,uBAAuB,CAAC,GAAW;IAC/C,MAAM,MAAM,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC;IAClC,IAAI,CAAC,MAAM,EAAE,QAAQ;QAAE,OAAO,MAAM,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,IAAI,EAAE,CAAC;IACvE,OAAO,wBAAwB,CAAC,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;AACnE,CAAC;AAED,8CAA8C;AAC9C,SAAS,yBAAyB,CAAC,KAAa;IAC5C,MAAM,CAAC,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IACrC,IAAI,CAAC,CAAC;QAAE,OAAO,EAAE,CAAC;IAClB,IAAI,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC;QAAE,OAAO,CAAC,CAAC;IAC9B,OAAO,CAAC,CAAC;AACb,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,oCAAoC,CAAC,UAAkB;IACnE,MAAM,IAAI,GAAG,UAAU,CAAC,IAAI,EAAE,CAAC;IAC/B,MAAM,WAAW,GAAG,qCAAqC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACrE,IAAI,WAAW,EAAE,CAAC,CAAC,CAAC;QAAE,OAAO,yBAAyB,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC;IACvE,MAAM,YAAY,GAAG,wCAAwC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACzE,IAAI,YAAY,EAAE,CAAC,CAAC,CAAC;QAAE,OAAO,yBAAyB,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC;IACzE,OAAO,SAAS,CAAC;AACrB,CAAC;AAED,MAAM,UAAU,qBAAqB,CACjC,YAAgC,EAChC,SAA6B;IAE7B,IAAI,CAAC,YAAY,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE;QAAE,OAAO,KAAK,CAAC;IAC9D,MAAM,YAAY,GAAG,uBAAuB,CAAC,YAAY,CAAC,CAAC;IAC3D,IAAI,CAAC,YAAY,IAAI,CAAC,SAAS;QAAE,OAAO,KAAK,CAAC;IAC9C,IAAI,YAAY,KAAK,SAAS;QAAE,OAAO,IAAI,CAAC;IAC5C,wEAAwE;IACxE,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,SAAS,CAAC,QAAQ,CAAC,IAAI,YAAY,EAAE,CAAC;QAAE,OAAO,IAAI,CAAC;IACvF,OAAO,KAAK,CAAC;AACjB,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,sCAAsC,CAAC,MAItD;IACG,IAAI,CAAC,MAAM,CAAC,gBAAgB;QAAE,OAAO,KAAK,CAAC;IAC3C,IAAI,CAAC,MAAM,CAAC,iBAAiB,EAAE,IAAI,EAAE;QAAE,OAAO,KAAK,CAAC;IACpD,MAAM,mBAAmB,GAAG,MAAM,CAAC,UAAU;QACzC,CAAC,CAAC,oCAAoC,CAAC,MAAM,CAAC,UAAU,CAAC;QACzD,CAAC,CAAC,SAAS,CAAC;IAChB,IAAI,CAAC,mBAAmB;QAAE,OAAO,KAAK,CAAC;IACvC,OAAO,qBAAqB,CAAC,MAAM,CAAC,iBAAiB,EAAE,mBAAmB,CAAC,CAAC;AAChF,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,iCAAiC,CAAC,MAKjD;IACG,IAAI,CAAC,MAAM,CAAC,gBAAgB;QAAE,OAAO,KAAK,CAAC;IAC3C,IAAI,MAAM,CAAC,0BAA0B,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IAC5D,OAAO,sCAAsC,CAAC;QAC1C,gBAAgB,EAAE,IAAI;QACtB,iBAAiB,EAAE,MAAM,CAAC,iBAAiB;QAC3C,UAAU,EAAE,MAAM,CAAC,UAAU;KAChC,CAAC,CAAC;AACP,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"per-message-fallback-notice.test.d.ts","sourceRoot":"","sources":["../../src/per-message-fallback-notice.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import { describe, it } from "node:test";
|
|
3
|
+
import { shouldDeliverModelFallbackNoticeToIm } from "./channel-config.js";
|
|
4
|
+
import { parseFallbackNoticeEffectiveModelRef, shouldSuppressFallbackNoticeForIm, shouldSuppressPerMessageFallbackNotice, } from "./per-message-fallback-notice.js";
|
|
5
|
+
function cfg(overrides = {}) {
|
|
6
|
+
return { baseUrl: "https://example.com", ...overrides };
|
|
7
|
+
}
|
|
8
|
+
const FALLBACK_NOTICE = "↪️ Model Fallback: newapi-xgjk/minimax-latest-cloud (selected newapi-xgjk/gemini-latest-cloud; auth)";
|
|
9
|
+
describe("model fallback notice for IM", () => {
|
|
10
|
+
it("shouldDeliverModelFallbackNoticeToIm is false unless explicitly true", () => {
|
|
11
|
+
assert.equal(shouldDeliverModelFallbackNoticeToIm(cfg()), false);
|
|
12
|
+
assert.equal(shouldDeliverModelFallbackNoticeToIm(cfg({ deliverModelFallbackNotice: false })), false);
|
|
13
|
+
assert.equal(shouldDeliverModelFallbackNoticeToIm(cfg({ deliverModelFallbackNotice: true })), true);
|
|
14
|
+
});
|
|
15
|
+
it("shouldSuppressFallbackNoticeForIm suppresses by default", () => {
|
|
16
|
+
assert.equal(shouldSuppressFallbackNoticeForIm({
|
|
17
|
+
isFallbackNotice: true,
|
|
18
|
+
noticeText: FALLBACK_NOTICE,
|
|
19
|
+
}), true);
|
|
20
|
+
});
|
|
21
|
+
it("shouldSuppressFallbackNoticeForIm delivers when enabled and not spurious", () => {
|
|
22
|
+
assert.equal(shouldSuppressFallbackNoticeForIm({
|
|
23
|
+
isFallbackNotice: true,
|
|
24
|
+
deliverModelFallbackNotice: true,
|
|
25
|
+
noticeText: FALLBACK_NOTICE,
|
|
26
|
+
}), false);
|
|
27
|
+
});
|
|
28
|
+
it("shouldSuppressFallbackNoticeForIm still suppresses spurious ai_model match when enabled", () => {
|
|
29
|
+
assert.equal(shouldSuppressFallbackNoticeForIm({
|
|
30
|
+
isFallbackNotice: true,
|
|
31
|
+
deliverModelFallbackNotice: true,
|
|
32
|
+
requestedModelRaw: "newapi-xgjk/minimax-latest-cloud",
|
|
33
|
+
noticeText: FALLBACK_NOTICE,
|
|
34
|
+
}), true);
|
|
35
|
+
});
|
|
36
|
+
it("parseFallbackNoticeEffectiveModelRef reads active model", () => {
|
|
37
|
+
assert.equal(parseFallbackNoticeEffectiveModelRef(FALLBACK_NOTICE), "newapi-xgjk/minimax-latest-cloud");
|
|
38
|
+
});
|
|
39
|
+
it("shouldSuppressPerMessageFallbackNotice ignores non-fallback payloads", () => {
|
|
40
|
+
assert.equal(shouldSuppressPerMessageFallbackNotice({
|
|
41
|
+
isFallbackNotice: false,
|
|
42
|
+
requestedModelRaw: "a/b",
|
|
43
|
+
noticeText: FALLBACK_NOTICE,
|
|
44
|
+
}), false);
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
//# sourceMappingURL=per-message-fallback-notice.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"per-message-fallback-notice.test.js","sourceRoot":"","sources":["../../src/per-message-fallback-notice.test.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,oBAAoB,CAAC;AACxC,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,EAAE,oCAAoC,EAAE,MAAM,qBAAqB,CAAC;AAC3E,OAAO,EACH,oCAAoC,EACpC,iCAAiC,EACjC,sCAAsC,GACzC,MAAM,kCAAkC,CAAC;AAG1C,SAAS,GAAG,CAAC,YAAiC,EAAE;IAC5C,OAAO,EAAE,OAAO,EAAE,qBAAqB,EAAE,GAAG,SAAS,EAAE,CAAC;AAC5D,CAAC;AAED,MAAM,eAAe,GACjB,sGAAsG,CAAC;AAE3G,QAAQ,CAAC,8BAA8B,EAAE,GAAG,EAAE;IAC1C,EAAE,CAAC,sEAAsE,EAAE,GAAG,EAAE;QAC5E,MAAM,CAAC,KAAK,CAAC,oCAAoC,CAAC,GAAG,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC;QACjE,MAAM,CAAC,KAAK,CAAC,oCAAoC,CAAC,GAAG,CAAC,EAAE,0BAA0B,EAAE,KAAK,EAAE,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;QACtG,MAAM,CAAC,KAAK,CAAC,oCAAoC,CAAC,GAAG,CAAC,EAAE,0BAA0B,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;IACxG,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yDAAyD,EAAE,GAAG,EAAE;QAC/D,MAAM,CAAC,KAAK,CACR,iCAAiC,CAAC;YAC9B,gBAAgB,EAAE,IAAI;YACtB,UAAU,EAAE,eAAe;SAC9B,CAAC,EACF,IAAI,CACP,CAAC;IACN,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0EAA0E,EAAE,GAAG,EAAE;QAChF,MAAM,CAAC,KAAK,CACR,iCAAiC,CAAC;YAC9B,gBAAgB,EAAE,IAAI;YACtB,0BAA0B,EAAE,IAAI;YAChC,UAAU,EAAE,eAAe;SAC9B,CAAC,EACF,KAAK,CACR,CAAC;IACN,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yFAAyF,EAAE,GAAG,EAAE;QAC/F,MAAM,CAAC,KAAK,CACR,iCAAiC,CAAC;YAC9B,gBAAgB,EAAE,IAAI;YACtB,0BAA0B,EAAE,IAAI;YAChC,iBAAiB,EAAE,kCAAkC;YACrD,UAAU,EAAE,eAAe;SAC9B,CAAC,EACF,IAAI,CACP,CAAC;IACN,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yDAAyD,EAAE,GAAG,EAAE;QAC/D,MAAM,CAAC,KAAK,CAAC,oCAAoC,CAAC,eAAe,CAAC,EAAE,kCAAkC,CAAC,CAAC;IAC5G,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sEAAsE,EAAE,GAAG,EAAE;QAC5E,MAAM,CAAC,KAAK,CACR,sCAAsC,CAAC;YACnC,gBAAgB,EAAE,KAAK;YACvB,iBAAiB,EAAE,KAAK;YACxB,UAAU,EAAE,eAAe;SAC9B,CAAC,EACF,KAAK,CACR,CAAC;IACN,CAAC,CAAC,CAAC;AACP,CAAC,CAAC,CAAC"}
|
|
@@ -8,8 +8,22 @@ export interface LocalRootSpec {
|
|
|
8
8
|
kind: LocalRootKind;
|
|
9
9
|
path: string;
|
|
10
10
|
}
|
|
11
|
+
/** 知识库目录 fileId(IM 信令 remoteRootFolderId → 同步服务 remoteRootFileId) */
|
|
12
|
+
export declare function normalizeRemoteRootFolderId(raw: string): string;
|
|
11
13
|
/** 知识库逻辑路径:去掉首部 `/`,统一为正斜杠分段 */
|
|
12
14
|
export declare function normalizeRemoteRootFolderPath(raw: string): string;
|
|
15
|
+
export interface ResolvedRemoteRoot {
|
|
16
|
+
/** 写入同步服务 body 的 remoteRootFileId */
|
|
17
|
+
remoteRootFileId?: string;
|
|
18
|
+
remoteRootFolderPath?: string;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* 解析 upsert 远端根:remoteRootFolderId 优先;两者都填时 id 决定同步根,path 仍透传供 upload 前缀。
|
|
22
|
+
*/
|
|
23
|
+
export declare function resolveRemoteRootForSync(params: {
|
|
24
|
+
remoteRootFolderId?: string;
|
|
25
|
+
remoteRootFolderPath?: string;
|
|
26
|
+
}): ResolvedRemoteRoot;
|
|
13
27
|
/** 规范化 workspace 相对段(去 ./、前导 /、尾部 /,禁止 ..) */
|
|
14
28
|
export declare function normalizeWorkspaceRelativeSegment(userPath: string): string;
|
|
15
29
|
export declare function resolveLocalAbsolutePath(localRoot: LocalRootSpec, workspaceHostRoot: string | undefined): string;
|