@jsonstudio/llms 0.6.3271 → 0.6.3379
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/dist/conversion/bridge-message-utils.d.ts +4 -4
- package/dist/conversion/bridge-message-utils.js +28 -538
- package/dist/conversion/compat/actions/anthropic-claude-code-system-prompt.js +38 -0
- package/dist/conversion/compat/profiles/responses-crs.json +15 -0
- package/dist/conversion/hub/operation-table/semantic-mappers/chat-mapper.js +16 -5
- package/dist/conversion/hub/pipeline/stages/resp_process/resp_process_stage1_tool_governance/index.js +1 -6
- package/dist/conversion/hub/response/response-runtime.js +14 -6
- package/dist/conversion/responses/responses-openai-bridge/response-payload.js +11 -11
- package/dist/conversion/shared/anthropic-message-utils.js +2 -12
- package/dist/conversion/shared/chat-request-filters.js +2 -61
- package/dist/conversion/shared/reasoning-mapping.js +3 -0
- package/dist/conversion/shared/reasoning-normalizer.d.ts +1 -0
- package/dist/conversion/shared/reasoning-normalizer.js +35 -388
- package/dist/conversion/shared/reasoning-tool-normalizer.js +8 -15
- package/dist/conversion/shared/reasoning-utils.js +13 -35
- package/dist/conversion/shared/responses-tool-utils.d.ts +1 -1
- package/dist/conversion/shared/responses-tool-utils.js +63 -65
- package/dist/conversion/shared/streaming-text-extractor.d.ts +0 -5
- package/dist/conversion/shared/streaming-text-extractor.js +18 -111
- package/dist/conversion/shared/text-markup-normalizer/normalize.d.ts +1 -1
- package/dist/conversion/shared/text-markup-normalizer/normalize.js +3 -91
- package/dist/conversion/shared/thought-signature-validator.js +19 -133
- package/dist/conversion/shared/tool-argument-repairer.js +16 -19
- package/dist/conversion/shared/tool-call-id-manager.d.ts +1 -5
- package/dist/conversion/shared/tool-call-id-manager.js +74 -98
- package/dist/conversion/shared/tool-harvester.js +19 -382
- package/dist/conversion/shared/tool-mapping.d.ts +2 -3
- package/dist/conversion/shared/tool-mapping.js +28 -184
- package/dist/conversion/shared/tooling.js +20 -151
- package/dist/filters/special/response-tool-arguments-stringify.js +9 -1
- package/dist/guidance/index.js +2 -2
- package/dist/native/router_hotpath_napi.node +0 -0
- package/dist/router/virtual-router/engine-legacy/helpers.js +1 -1
- package/dist/router/virtual-router/engine-selection/native-hub-bridge-action-semantics.d.ts +39 -0
- package/dist/router/virtual-router/engine-selection/native-hub-bridge-action-semantics.js +196 -0
- package/dist/router/virtual-router/engine-selection/native-hub-pipeline-req-inbound-semantics.d.ts +1 -0
- package/dist/router/virtual-router/engine-selection/native-hub-pipeline-req-inbound-semantics.js +27 -0
- package/dist/router/virtual-router/engine-selection/native-router-hotpath-loader.js +34 -0
- package/dist/router/virtual-router/engine-selection/native-shared-conversion-semantics.d.ts +65 -1
- package/dist/router/virtual-router/engine-selection/native-shared-conversion-semantics.js +836 -35
- package/dist/router/virtual-router/engine.js +3 -2
- package/dist/router/virtual-router/routing-instructions/parse.js +30 -3
- package/dist/sse/sse-to-json/builders/anthropic-response-builder.js +28 -3
- package/dist/sse/types/anthropic-types.d.ts +3 -1
- package/dist/tools/apply-patch/args-normalizer/extract-patch.js +2 -2
- package/dist/tools/apply-patch/patch-text/looks-like-patch.js +3 -6
- package/dist/tools/apply-patch/patch-text/normalize.js +14 -3
- package/dist/tools/tool-registry.js +12 -0
- package/package.json +6 -1
|
@@ -4,6 +4,7 @@ import { parseRoutingInstructions } from './routing-instructions/parse.js';
|
|
|
4
4
|
import { createVirtualRouterEngineProxy } from './engine-selection/native-virtual-router-engine-proxy.js';
|
|
5
5
|
import { cleanRoutingInstructionMarkersWithNative, parseRoutingInstructionKindsWithNative } from './engine-selection/native-virtual-router-routing-instructions-semantics.js';
|
|
6
6
|
import { getLatestUserTextFromResponsesContext, hasLatestUserRoutingInstructionMarker, hasRoutingInstructionMarkerInResponsesContext } from './engine-legacy/helpers.js';
|
|
7
|
+
import { extractMessageText, getLatestUserMessage } from './message-utils.js';
|
|
7
8
|
import { ProviderRegistry } from './provider-registry.js';
|
|
8
9
|
import { resolveStopMessageScope } from './engine/routing-state/store.js';
|
|
9
10
|
import { loadRoutingInstructionStateSync } from './sticky-session-store.js';
|
|
@@ -225,8 +226,8 @@ function buildRoutingInstructionParseLog(request, metadata) {
|
|
|
225
226
|
if (!messages.length) {
|
|
226
227
|
return null;
|
|
227
228
|
}
|
|
228
|
-
const latest = messages
|
|
229
|
-
const latestText =
|
|
229
|
+
const latest = getLatestUserMessage(messages);
|
|
230
|
+
const latestText = latest ? extractMessageText(latest).trim() : '';
|
|
230
231
|
const parsedKinds = parseRoutingInstructionKindsWithNative(request);
|
|
231
232
|
const stopMessageTypes = parsedKinds.filter((type) => type === 'stopMessageSet' || type === 'stopMessageMode' || type === 'stopMessageClear');
|
|
232
233
|
const scopedTypes = parsedKinds.filter((type) => type === 'stopMessageSet' ||
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { extractMessageText } from '../message-utils.js';
|
|
1
|
+
import { extractMessageText, getLatestUserMessage } from '../message-utils.js';
|
|
2
2
|
import { parseStopMessageInstruction } from '../routing-stop-message-parser.js';
|
|
3
3
|
import { parsePreCommandInstruction } from '../routing-pre-command-parser.js';
|
|
4
4
|
import { stripCodeSegments } from './clean.js';
|
|
@@ -6,8 +6,8 @@ import { ROUTING_INSTRUCTION_MARKER_PATTERN } from './types.js';
|
|
|
6
6
|
export function parseRoutingInstructions(messages) {
|
|
7
7
|
const instructions = [];
|
|
8
8
|
// 只解析“当前最新一条消息”中的 marker,避免历史 user marker 在后续轮次被重复回放。
|
|
9
|
-
const latestMessage = messages
|
|
10
|
-
if (!latestMessage
|
|
9
|
+
const latestMessage = getLatestUserMessage(messages);
|
|
10
|
+
if (!latestMessage) {
|
|
11
11
|
return instructions;
|
|
12
12
|
}
|
|
13
13
|
const content = extractMessageText(latestMessage);
|
|
@@ -87,6 +87,10 @@ function expandInstructionSegments(instruction) {
|
|
|
87
87
|
if (/^precommand(?:\s*:|$)/i.test(normalizedLeading)) {
|
|
88
88
|
return [normalizedLeading];
|
|
89
89
|
}
|
|
90
|
+
const quotedStopMessage = normalizeQuotedStopMessageShorthand(normalizedLeading);
|
|
91
|
+
if (quotedStopMessage) {
|
|
92
|
+
return [normalizeStopMessageCommandPrefix(quotedStopMessage)];
|
|
93
|
+
}
|
|
90
94
|
const prefix = trimmed[0];
|
|
91
95
|
if (prefix === '!' || prefix === '#' || prefix === '@') {
|
|
92
96
|
const tokens = splitInstructionTargets(trimmed.substring(1));
|
|
@@ -121,6 +125,29 @@ function normalizeSplitStopMessageHeadToken(token) {
|
|
|
121
125
|
.replace(/^["']+|["']+$/g, '')
|
|
122
126
|
.trim();
|
|
123
127
|
}
|
|
128
|
+
function normalizeQuotedStopMessageShorthand(content) {
|
|
129
|
+
const normalized = normalizeInstructionLeading(content);
|
|
130
|
+
const quote = normalized[0];
|
|
131
|
+
if (quote !== '"' && quote !== "'") {
|
|
132
|
+
return null;
|
|
133
|
+
}
|
|
134
|
+
let escaped = false;
|
|
135
|
+
for (let idx = 1; idx < normalized.length; idx += 1) {
|
|
136
|
+
const ch = normalized[idx];
|
|
137
|
+
if (escaped) {
|
|
138
|
+
escaped = false;
|
|
139
|
+
continue;
|
|
140
|
+
}
|
|
141
|
+
if (ch === '\\') {
|
|
142
|
+
escaped = true;
|
|
143
|
+
continue;
|
|
144
|
+
}
|
|
145
|
+
if (ch === quote) {
|
|
146
|
+
return `stopMessage:${normalized}`;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
return null;
|
|
150
|
+
}
|
|
124
151
|
function recoverSplitStopMessageInstruction(tokens) {
|
|
125
152
|
if (!Array.isArray(tokens) || tokens.length < 2) {
|
|
126
153
|
return null;
|
|
@@ -1,4 +1,23 @@
|
|
|
1
1
|
import { dispatchReasoning } from '../../shared/reasoning-dispatcher.js';
|
|
2
|
+
function mergeAnthropicUsage(current, incoming) {
|
|
3
|
+
if (!incoming || typeof incoming !== 'object') {
|
|
4
|
+
return current;
|
|
5
|
+
}
|
|
6
|
+
const incomingRecord = incoming;
|
|
7
|
+
const base = current && typeof current === 'object' ? { ...current } : {};
|
|
8
|
+
for (const [key, value] of Object.entries(incomingRecord)) {
|
|
9
|
+
if (value && typeof value === 'object' && !Array.isArray(value)) {
|
|
10
|
+
const prev = base[key];
|
|
11
|
+
base[key] = {
|
|
12
|
+
...(prev && typeof prev === 'object' && !Array.isArray(prev) ? prev : {}),
|
|
13
|
+
...value
|
|
14
|
+
};
|
|
15
|
+
continue;
|
|
16
|
+
}
|
|
17
|
+
base[key] = value;
|
|
18
|
+
}
|
|
19
|
+
return base;
|
|
20
|
+
}
|
|
2
21
|
export function createAnthropicResponseBuilder(options) {
|
|
3
22
|
const state = {
|
|
4
23
|
content: [],
|
|
@@ -58,6 +77,7 @@ export function createAnthropicResponseBuilder(options) {
|
|
|
58
77
|
state.id = payload.id || state.id;
|
|
59
78
|
state.model = payload.model || state.model;
|
|
60
79
|
state.role = payload.role || state.role;
|
|
80
|
+
state.usage = mergeAnthropicUsage(state.usage, payload.usage);
|
|
61
81
|
}
|
|
62
82
|
break;
|
|
63
83
|
}
|
|
@@ -116,11 +136,14 @@ export function createAnthropicResponseBuilder(options) {
|
|
|
116
136
|
if (delta?.stop_reason) {
|
|
117
137
|
state.stopReason = delta.stop_reason;
|
|
118
138
|
}
|
|
139
|
+
if (typeof delta?.stop_sequence === 'string' || delta?.stop_sequence === null) {
|
|
140
|
+
state.stopSequence = delta.stop_sequence;
|
|
141
|
+
}
|
|
119
142
|
// 部分实现将 usage 挂在 delta.usage,部分实现挂在顶层 event.data.usage,
|
|
120
143
|
// 这里统一优先读取 delta.usage,缺失时回退到 data.usage。
|
|
121
144
|
const usageNode = (delta && delta.usage) ?? data.usage;
|
|
122
145
|
if (usageNode) {
|
|
123
|
-
state.usage = usageNode;
|
|
146
|
+
state.usage = mergeAnthropicUsage(state.usage, usageNode);
|
|
124
147
|
}
|
|
125
148
|
break;
|
|
126
149
|
}
|
|
@@ -151,7 +174,8 @@ export function createAnthropicResponseBuilder(options) {
|
|
|
151
174
|
model: state.model || 'unknown',
|
|
152
175
|
content: state.content,
|
|
153
176
|
usage: state.usage,
|
|
154
|
-
stop_reason: state.stopReason ?? 'end_turn'
|
|
177
|
+
stop_reason: state.stopReason ?? 'end_turn',
|
|
178
|
+
stop_sequence: state.stopSequence
|
|
155
179
|
}
|
|
156
180
|
};
|
|
157
181
|
}
|
|
@@ -166,7 +190,8 @@ export function createAnthropicResponseBuilder(options) {
|
|
|
166
190
|
model: state.model || 'unknown',
|
|
167
191
|
content: state.content,
|
|
168
192
|
usage: state.usage,
|
|
169
|
-
stop_reason: state.stopReason ?? 'end_turn'
|
|
193
|
+
stop_reason: state.stopReason ?? 'end_turn',
|
|
194
|
+
stop_sequence: state.stopSequence
|
|
170
195
|
}
|
|
171
196
|
};
|
|
172
197
|
}
|
|
@@ -30,11 +30,12 @@ export interface AnthropicMessageResponse {
|
|
|
30
30
|
role: 'assistant' | 'user';
|
|
31
31
|
model: string;
|
|
32
32
|
content: AnthropicContentBlock[];
|
|
33
|
-
usage?: {
|
|
33
|
+
usage?: Record<string, unknown> & {
|
|
34
34
|
input_tokens?: number;
|
|
35
35
|
output_tokens?: number;
|
|
36
36
|
};
|
|
37
37
|
stop_reason?: 'end_turn' | 'max_tokens' | 'stop_sequence' | 'tool_use';
|
|
38
|
+
stop_sequence?: string | null;
|
|
38
39
|
}
|
|
39
40
|
export interface AnthropicEventStats {
|
|
40
41
|
totalEvents: number;
|
|
@@ -157,6 +158,7 @@ export interface AnthropicSseEventMessageDelta extends AnthropicSseEventBase<'me
|
|
|
157
158
|
type: 'message_delta';
|
|
158
159
|
delta?: {
|
|
159
160
|
stop_reason?: AnthropicMessageResponse['stop_reason'];
|
|
161
|
+
stop_sequence?: string | null;
|
|
160
162
|
usage?: AnthropicMessageResponse['usage'];
|
|
161
163
|
};
|
|
162
164
|
};
|
|
@@ -4,11 +4,11 @@ export function extractNormalizedPatch(value) {
|
|
|
4
4
|
return {};
|
|
5
5
|
}
|
|
6
6
|
const normalized = normalizeApplyPatchText(value);
|
|
7
|
-
const patchLike = looksLikePatch(value) || looksLikePatch(normalized)
|
|
7
|
+
const patchLike = looksLikePatch(value) || looksLikePatch(normalized);
|
|
8
8
|
if (!patchLike) {
|
|
9
9
|
return {};
|
|
10
10
|
}
|
|
11
|
-
if (
|
|
11
|
+
if (!/^(?:\s*)\*\*\*\s*Begin Patch\b/m.test(normalized)) {
|
|
12
12
|
return { failureReason: 'unsupported_patch_format' };
|
|
13
13
|
}
|
|
14
14
|
return { patchText: normalized };
|
|
@@ -4,11 +4,8 @@ export const looksLikePatch = (text) => {
|
|
|
4
4
|
const t = text.trim();
|
|
5
5
|
if (!t)
|
|
6
6
|
return false;
|
|
7
|
-
return (
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
t.includes('*** Create File:') ||
|
|
11
|
-
t.includes('*** Delete File:') ||
|
|
12
|
-
t.includes('diff --git') ||
|
|
7
|
+
return (/^(?:\s*)\*\*\*\s*Begin Patch\b/m.test(t) ||
|
|
8
|
+
/^(?:\s*)\*\*\*\s*(?:Update|Add|Create|Delete)\s+File:/m.test(t) ||
|
|
9
|
+
/^diff --git\s/m.test(t) ||
|
|
13
10
|
/^(?:@@|\+\+\+\s|---\s)/m.test(t));
|
|
14
11
|
};
|
|
@@ -109,18 +109,29 @@ const convertStarHeaderDiffToApplyPatchIfPossible = (text) => {
|
|
|
109
109
|
return null;
|
|
110
110
|
}
|
|
111
111
|
};
|
|
112
|
+
const normalizeApplyPatchHeaderPath = (raw) => {
|
|
113
|
+
let out = String(raw ?? '').trim();
|
|
114
|
+
if (!out)
|
|
115
|
+
return out;
|
|
116
|
+
if ((out.startsWith('"') && out.endsWith('"')) ||
|
|
117
|
+
(out.startsWith("'") && out.endsWith("'")) ||
|
|
118
|
+
(out.startsWith('`') && out.endsWith('`'))) {
|
|
119
|
+
out = out.slice(1, -1).trim();
|
|
120
|
+
}
|
|
121
|
+
return out;
|
|
122
|
+
};
|
|
112
123
|
const normalizeApplyPatchFileHeader = (line) => {
|
|
113
124
|
const addMatch = line.match(/^\*\*\* Add File:\s*(.+?)(?:\s+\*\*\*)?\s*$/);
|
|
114
125
|
if (addMatch && addMatch[1]) {
|
|
115
|
-
return `*** Add File: ${addMatch[1]
|
|
126
|
+
return `*** Add File: ${normalizeApplyPatchHeaderPath(addMatch[1])}`;
|
|
116
127
|
}
|
|
117
128
|
const updateMatch = line.match(/^\*\*\* Update File:\s*(.+?)(?:\s+\*\*\*)?\s*$/);
|
|
118
129
|
if (updateMatch && updateMatch[1]) {
|
|
119
|
-
return `*** Update File: ${updateMatch[1]
|
|
130
|
+
return `*** Update File: ${normalizeApplyPatchHeaderPath(updateMatch[1])}`;
|
|
120
131
|
}
|
|
121
132
|
const deleteMatch = line.match(/^\*\*\* Delete File:\s*(.+?)(?:\s+\*\*\*)?\s*$/);
|
|
122
133
|
if (deleteMatch && deleteMatch[1]) {
|
|
123
|
-
return `*** Delete File: ${deleteMatch[1]
|
|
134
|
+
return `*** Delete File: ${normalizeApplyPatchHeaderPath(deleteMatch[1])}`;
|
|
124
135
|
}
|
|
125
136
|
return line;
|
|
126
137
|
};
|
|
@@ -72,6 +72,8 @@ const isImagePath = (value) => {
|
|
|
72
72
|
export function getAllowedToolNames() {
|
|
73
73
|
return [
|
|
74
74
|
'shell',
|
|
75
|
+
'shell_command',
|
|
76
|
+
'bash',
|
|
75
77
|
'exec_command',
|
|
76
78
|
'apply_patch',
|
|
77
79
|
'update_plan',
|
|
@@ -108,6 +110,16 @@ export function validateToolCall(name, argsString, options) {
|
|
|
108
110
|
}
|
|
109
111
|
return { ok: true, normalizedArgs: validation.normalizedArgs };
|
|
110
112
|
}
|
|
113
|
+
case 'shell_command':
|
|
114
|
+
case 'bash': {
|
|
115
|
+
const rawArgs = isRecord(rawArgsAny) ? rawArgsAny : {};
|
|
116
|
+
const command = asString(rawArgs.command) ??
|
|
117
|
+
asString(rawArgs.cmd);
|
|
118
|
+
if (!command) {
|
|
119
|
+
return { ok: false, reason: 'missing_command' };
|
|
120
|
+
}
|
|
121
|
+
return { ok: true, normalizedArgs: toJson(rawArgs) };
|
|
122
|
+
}
|
|
111
123
|
case 'apply_patch': {
|
|
112
124
|
const validation = validateApplyPatchArgs(argsString, rawArgsAny);
|
|
113
125
|
if (!validation.ok) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jsonstudio/llms",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.3379",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.js",
|
|
@@ -78,6 +78,7 @@
|
|
|
78
78
|
"test:coverage:hub-resp-outbound-client-remap-switch": "npm run build:ci && node ./node_modules/c8/bin/c8.js --reporter=json-summary --reporter=text --report-dir=coverage/module-hub-resp-outbound-client-remap-switch --include=dist/conversion/hub/pipeline/stages/resp_outbound/resp_outbound_stage1_client_remap/client-remap-protocol-switch.js --exclude=scripts/** node scripts/tests/coverage-hub-resp-outbound-client-remap-protocol-switch.mjs",
|
|
79
79
|
"test:coverage:virtual-router-tier-antigravity-session-lease": "npm run build:ci && node ./node_modules/c8/bin/c8.js --reporter=json-summary --reporter=text --report-dir=coverage/module-virtual-router-tier-antigravity-session-lease --include=dist/router/virtual-router/engine-selection/tier-selection-antigravity-session-lease.js --exclude=scripts/** node scripts/tests/coverage-virtual-router-tier-antigravity-session-lease.mjs",
|
|
80
80
|
"test:coverage:virtual-router-tier-antigravity-target-split": "npm run build:ci && node ./node_modules/c8/bin/c8.js --reporter=json-summary --reporter=text --report-dir=coverage/module-virtual-router-tier-antigravity-target-split --include=dist/router/virtual-router/engine-selection/tier-selection-antigravity-target-split.js --exclude=scripts/** node scripts/tests/coverage-virtual-router-tier-antigravity-target-split.mjs",
|
|
81
|
+
"test:coverage:text-markup-normalizer": "npm run build:ci && C8_COVERAGE=1 node ./node_modules/c8/bin/c8.js --lines 95 --branches 95 --functions 95 --statements 95 --reporter=json-summary --reporter=text --report-dir=coverage/module-text-markup-normalizer --include=dist/conversion/shared/text-markup-normalizer.js --exclude=**/node_modules/** node scripts/tests/coverage-text-markup-normalizer.mjs",
|
|
81
82
|
"test:coverage": "node scripts/run-ci-coverage.mjs",
|
|
82
83
|
"verify:module-blackbox": "node scripts/tests/module-blackbox-gate.mjs",
|
|
83
84
|
"verify:shadow-gate": "node scripts/check-shadow-coverage-gate.mjs",
|
|
@@ -141,6 +142,7 @@
|
|
|
141
142
|
"verify:shadow-gate:hub-resp-outbound-sse-stream": "npm run test:coverage:hub-resp-outbound-sse-stream && node scripts/check-shadow-coverage-gate.mjs --summary coverage/module-hub-resp-outbound-sse-stream/coverage-summary.json --module hub.resp-outbound.sse-stream && node scripts/promote-shadow-module.mjs --module hub.resp-outbound.sse-stream",
|
|
142
143
|
"verify:shadow-gate:hub-native-batch": "npm run test:coverage:hub-native-batch && node scripts/check-shadow-coverage-gate.mjs --summary coverage/module-hub-native-batch/coverage-summary.json --module hub.native-batch.adapters-snapshot-governance && node scripts/promote-shadow-module.mjs --module hub.native-batch.adapters-snapshot-governance",
|
|
143
144
|
"test:coverage:hub-chat-request-filters": "npm run build:ci && node ./node_modules/c8/bin/c8.js --reporter=json-summary --reporter=text --report-dir=coverage/module-hub-chat-request-filters --include=dist/conversion/shared/chat-request-filters.js --include=dist/router/virtual-router/engine-selection/native-chat-request-filter-semantics.js --exclude=scripts/** node scripts/tests/coverage-chat-request-filters.mjs",
|
|
145
|
+
"test:coverage:router-hotpath-napi": "cd rust-core && cargo llvm-cov -p router-hotpath-napi --summary-only --json --output-path /tmp/router-hotpath-napi-cov.json && node -e \"const fs=require('fs');const data=JSON.parse(fs.readFileSync('/tmp/router-hotpath-napi-cov.json','utf8'));const files=(data.data&&data.data[0]&&data.data[0].files)||[];const target=files.find(f=>String(f.filename||'').endsWith('resp_process_stage1_tool_governance.rs'));if(!target){console.error('missing resp_process_stage1_tool_governance.rs in coverage');process.exit(1);}const sum=target.summary||{};const lines=sum.lines?sum.lines.percent:0;const funcs=sum.functions?sum.functions.percent:0;const regions=sum.regions?sum.regions.percent:0;const branches=sum.branches?sum.branches.percent:'n/a';const statements=sum.statements?sum.statements.percent:'n/a';console.log('[coverage router-hotpath-napi] lines',lines,'functions',funcs,'regions',regions,'branches',branches,'statements',statements);const min=95;if(lines<min||funcs<min||regions<min){process.exit(1);}\"",
|
|
144
146
|
"verify:shadow-gate:hub-chat-request-filters": "npm run test:coverage:hub-chat-request-filters && node scripts/check-shadow-coverage-gate.mjs --summary coverage/module-hub-chat-request-filters/coverage-summary.json --module hub.shared.chat-request-filters && node scripts/promote-shadow-module.mjs --module hub.shared.chat-request-filters"
|
|
145
147
|
},
|
|
146
148
|
"dependencies": {
|
|
@@ -167,11 +169,14 @@
|
|
|
167
169
|
}
|
|
168
170
|
},
|
|
169
171
|
"devDependencies": {
|
|
172
|
+
"@types/jest": "^29.5.14",
|
|
170
173
|
"@types/node": "^20.11.25",
|
|
171
174
|
"@typescript-eslint/eslint-plugin": "^8.56.1",
|
|
172
175
|
"@typescript-eslint/parser": "^8.56.1",
|
|
173
176
|
"c8": "^11.0.0",
|
|
174
177
|
"eslint": "^8.50.0",
|
|
178
|
+
"jest": "^29.7.0",
|
|
179
|
+
"ts-jest": "^29.2.6",
|
|
175
180
|
"tsx": "^4.21.0",
|
|
176
181
|
"typescript": "^5.4.0"
|
|
177
182
|
},
|