@jsonstudio/llms 0.6.1892 → 0.6.2172

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.
Files changed (159) hide show
  1. package/dist/conversion/compat/actions/deepseek-web-request.js +16 -2
  2. package/dist/conversion/compat/actions/deepseek-web-response.d.ts +7 -1
  3. package/dist/conversion/compat/actions/deepseek-web-response.js +302 -40
  4. package/dist/conversion/compat/actions/harvest-tool-calls-from-text.d.ts +5 -0
  5. package/dist/conversion/compat/actions/harvest-tool-calls-from-text.js +7 -4
  6. package/dist/conversion/compat/actions/iflow-tool-text-fallback.d.ts +1 -0
  7. package/dist/conversion/compat/actions/iflow-tool-text-fallback.js +12 -0
  8. package/dist/conversion/compat/actions/strip-orphan-function-calls-tag.js +1 -1
  9. package/dist/conversion/compat/actions/tool-text-request-guidance.d.ts +9 -0
  10. package/dist/conversion/compat/actions/tool-text-request-guidance.js +177 -0
  11. package/dist/conversion/compat/antigravity-session-signature.d.ts +6 -0
  12. package/dist/conversion/compat/antigravity-session-signature.js +15 -0
  13. package/dist/conversion/compat/profiles/chat-deepseek-web.json +52 -1
  14. package/dist/conversion/compat/profiles/chat-glm.json +22 -0
  15. package/dist/conversion/compat/profiles/chat-iflow.json +4 -0
  16. package/dist/conversion/hub/operation-table/semantic-mappers/gemini-mapper.js +13 -27
  17. package/dist/conversion/hub/operation-table/semantic-mappers/responses-mapper.js +10 -1
  18. package/dist/conversion/hub/pipeline/compat/compat-pipeline-executor.js +13 -4
  19. package/dist/conversion/hub/pipeline/compat/compat-profile-resolver.js +1 -53
  20. package/dist/conversion/hub/pipeline/compat/compat-types.d.ts +8 -0
  21. package/dist/conversion/hub/pipeline/hub-pipeline.js +8 -4
  22. package/dist/conversion/hub/pipeline/stages/req_inbound/req_inbound_stage3_context_capture/index.js +191 -9
  23. package/dist/conversion/hub/pipeline/stages/resp_inbound/resp_inbound_stage1_sse_decode/index.js +118 -15
  24. package/dist/conversion/hub/pipeline/stages/resp_process/resp_process_stage1_tool_governance/index.js +65 -2
  25. package/dist/conversion/hub/pipeline/stages/resp_process/resp_process_stage3_servertool_orchestration/index.d.ts +34 -0
  26. package/dist/conversion/hub/pipeline/stages/resp_process/resp_process_stage3_servertool_orchestration/index.js +75 -0
  27. package/dist/conversion/hub/process/chat-process.js +85 -18
  28. package/dist/conversion/hub/response/provider-response.js +21 -50
  29. package/dist/conversion/hub/response/response-runtime.js +71 -10
  30. package/dist/conversion/responses/responses-openai-bridge/response-payload.d.ts +3 -0
  31. package/dist/conversion/responses/responses-openai-bridge/response-payload.js +576 -0
  32. package/dist/conversion/responses/responses-openai-bridge/types.d.ts +42 -0
  33. package/dist/conversion/responses/responses-openai-bridge/types.js +1 -0
  34. package/dist/conversion/responses/responses-openai-bridge.d.ts +3 -44
  35. package/dist/conversion/responses/responses-openai-bridge.js +193 -504
  36. package/dist/conversion/shared/anthropic-message-utils.js +82 -2
  37. package/dist/conversion/shared/bridge-message-utils.js +92 -39
  38. package/dist/conversion/shared/snapshot-hooks.js +8 -13
  39. package/dist/conversion/shared/text-markup-normalizer/extractors-apply-patch.d.ts +2 -0
  40. package/dist/conversion/shared/text-markup-normalizer/extractors-apply-patch.js +129 -0
  41. package/dist/conversion/shared/text-markup-normalizer/extractors-json.d.ts +4 -0
  42. package/dist/conversion/shared/text-markup-normalizer/extractors-json.js +637 -0
  43. package/dist/conversion/shared/text-markup-normalizer/extractors-shared.d.ts +21 -0
  44. package/dist/conversion/shared/text-markup-normalizer/extractors-shared.js +177 -0
  45. package/dist/conversion/shared/text-markup-normalizer/extractors-transcript.d.ts +5 -0
  46. package/dist/conversion/shared/text-markup-normalizer/extractors-transcript.js +385 -0
  47. package/dist/conversion/shared/text-markup-normalizer/extractors-xml.d.ts +10 -0
  48. package/dist/conversion/shared/text-markup-normalizer/extractors-xml.js +602 -0
  49. package/dist/conversion/shared/text-markup-normalizer/extractors.d.ts +5 -0
  50. package/dist/conversion/shared/text-markup-normalizer/extractors.js +4 -0
  51. package/dist/conversion/shared/text-markup-normalizer/normalize.d.ts +2 -0
  52. package/dist/conversion/shared/text-markup-normalizer/normalize.js +76 -0
  53. package/dist/conversion/shared/text-markup-normalizer.d.ts +3 -25
  54. package/dist/conversion/shared/text-markup-normalizer.js +2 -1386
  55. package/dist/conversion/shared/tool-governor.js +136 -10
  56. package/dist/filters/utils/snapshot-writer.js +3 -3
  57. package/dist/router/virtual-router/bootstrap/auth-utils.d.ts +6 -0
  58. package/dist/router/virtual-router/bootstrap/auth-utils.js +288 -0
  59. package/dist/router/virtual-router/bootstrap/claude-code-helpers.d.ts +11 -0
  60. package/dist/router/virtual-router/bootstrap/claude-code-helpers.js +18 -0
  61. package/dist/router/virtual-router/bootstrap/config-defaults.d.ts +5 -0
  62. package/dist/router/virtual-router/bootstrap/config-defaults.js +13 -0
  63. package/dist/router/virtual-router/bootstrap/config-normalizers.d.ts +4 -0
  64. package/dist/router/virtual-router/bootstrap/config-normalizers.js +106 -0
  65. package/dist/router/virtual-router/bootstrap/profile-builder.d.ts +7 -0
  66. package/dist/router/virtual-router/bootstrap/profile-builder.js +68 -0
  67. package/dist/router/virtual-router/bootstrap/provider-normalization.d.ts +40 -0
  68. package/dist/router/virtual-router/bootstrap/provider-normalization.js +212 -0
  69. package/dist/router/virtual-router/bootstrap/responses-helpers.d.ts +15 -0
  70. package/dist/router/virtual-router/bootstrap/responses-helpers.js +65 -0
  71. package/dist/router/virtual-router/bootstrap/routing-config.d.ts +23 -0
  72. package/dist/router/virtual-router/bootstrap/routing-config.js +293 -0
  73. package/dist/router/virtual-router/bootstrap/streaming-helpers.d.ts +12 -0
  74. package/dist/router/virtual-router/bootstrap/streaming-helpers.js +128 -0
  75. package/dist/router/virtual-router/bootstrap/utils.d.ts +5 -0
  76. package/dist/router/virtual-router/bootstrap/utils.js +41 -0
  77. package/dist/router/virtual-router/bootstrap/web-search-config.d.ts +4 -0
  78. package/dist/router/virtual-router/bootstrap/web-search-config.js +131 -0
  79. package/dist/router/virtual-router/bootstrap.d.ts +0 -4
  80. package/dist/router/virtual-router/bootstrap.js +31 -1275
  81. package/dist/router/virtual-router/classifier.js +32 -14
  82. package/dist/router/virtual-router/engine/antigravity/alias-lease.js +2 -2
  83. package/dist/router/virtual-router/engine/cooldown-manager.d.ts +34 -0
  84. package/dist/router/virtual-router/engine/cooldown-manager.js +118 -0
  85. package/dist/router/virtual-router/engine/route-analytics.d.ts +28 -0
  86. package/dist/router/virtual-router/engine/route-analytics.js +44 -0
  87. package/dist/router/virtual-router/engine/routing-pools/index.js +165 -4
  88. package/dist/router/virtual-router/engine/sticky-session-manager.d.ts +29 -0
  89. package/dist/router/virtual-router/engine/sticky-session-manager.js +55 -0
  90. package/dist/router/virtual-router/engine-logging.d.ts +42 -1
  91. package/dist/router/virtual-router/engine-logging.js +82 -15
  92. package/dist/router/virtual-router/engine-selection/multimodal-capability.d.ts +3 -0
  93. package/dist/router/virtual-router/engine-selection/multimodal-capability.js +26 -0
  94. package/dist/router/virtual-router/engine-selection/route-utils.js +6 -2
  95. package/dist/router/virtual-router/engine-selection/selection-deps.d.ts +1 -0
  96. package/dist/router/virtual-router/engine-selection/tier-selection.js +31 -1
  97. package/dist/router/virtual-router/engine.d.ts +21 -7
  98. package/dist/router/virtual-router/engine.js +198 -194
  99. package/dist/router/virtual-router/features.js +12 -4
  100. package/dist/router/virtual-router/message-utils.d.ts +8 -0
  101. package/dist/router/virtual-router/message-utils.js +170 -45
  102. package/dist/router/virtual-router/pre-command-file-resolver.js +40 -2
  103. package/dist/router/virtual-router/routing-instructions.d.ts +8 -0
  104. package/dist/router/virtual-router/routing-instructions.js +18 -2
  105. package/dist/router/virtual-router/routing-stop-message-actions.js +34 -10
  106. package/dist/router/virtual-router/routing-stop-message-state-codec.d.ts +2 -0
  107. package/dist/router/virtual-router/routing-stop-message-state-codec.js +50 -1
  108. package/dist/router/virtual-router/stop-message-state-sync.d.ts +1 -1
  109. package/dist/router/virtual-router/stop-message-state-sync.js +3 -0
  110. package/dist/router/virtual-router/token-counter.js +51 -10
  111. package/dist/router/virtual-router/tool-signals.js +4 -0
  112. package/dist/router/virtual-router/types.d.ts +15 -0
  113. package/dist/servertool/clock/session-scope.d.ts +3 -0
  114. package/dist/servertool/clock/session-scope.js +52 -0
  115. package/dist/servertool/clock/state.js +9 -0
  116. package/dist/servertool/clock/tasks.js +12 -1
  117. package/dist/servertool/clock/types.d.ts +3 -0
  118. package/dist/servertool/engine.js +177 -31
  119. package/dist/servertool/handlers/clock-auto.js +2 -8
  120. package/dist/servertool/handlers/clock.js +6 -9
  121. package/dist/servertool/handlers/recursive-detection-guard.js +53 -14
  122. package/dist/servertool/handlers/stop-message-auto/blocked-report.d.ts +16 -0
  123. package/dist/servertool/handlers/stop-message-auto/blocked-report.js +349 -0
  124. package/dist/servertool/handlers/stop-message-auto/iflow-followup.d.ts +23 -0
  125. package/dist/servertool/handlers/stop-message-auto/iflow-followup.js +503 -0
  126. package/dist/servertool/handlers/stop-message-auto/routing-state.d.ts +38 -0
  127. package/dist/servertool/handlers/stop-message-auto/routing-state.js +149 -0
  128. package/dist/servertool/handlers/stop-message-auto/runtime-utils.d.ts +67 -0
  129. package/dist/servertool/handlers/stop-message-auto/runtime-utils.js +387 -0
  130. package/dist/servertool/handlers/stop-message-auto.d.ts +1 -1
  131. package/dist/servertool/handlers/stop-message-auto.js +80 -556
  132. package/dist/servertool/handlers/stop-message-stage-policy/bd-runtime.d.ts +18 -0
  133. package/dist/servertool/handlers/stop-message-stage-policy/bd-runtime.js +398 -0
  134. package/dist/servertool/handlers/stop-message-stage-policy/decision.d.ts +9 -0
  135. package/dist/servertool/handlers/stop-message-stage-policy/decision.js +127 -0
  136. package/dist/servertool/handlers/stop-message-stage-policy/observation.d.ts +2 -0
  137. package/dist/servertool/handlers/stop-message-stage-policy/observation.js +179 -0
  138. package/dist/servertool/handlers/stop-message-stage-policy/templates.d.ts +4 -0
  139. package/dist/servertool/handlers/stop-message-stage-policy/templates.js +96 -0
  140. package/dist/servertool/handlers/stop-message-stage-policy/text-utils.d.ts +9 -0
  141. package/dist/servertool/handlers/stop-message-stage-policy/text-utils.js +89 -0
  142. package/dist/servertool/handlers/stop-message-stage-policy/types.d.ts +59 -0
  143. package/dist/servertool/handlers/stop-message-stage-policy/types.js +1 -0
  144. package/dist/servertool/handlers/stop-message-stage-policy.d.ts +3 -43
  145. package/dist/servertool/handlers/stop-message-stage-policy.js +2 -684
  146. package/dist/servertool/handlers/web-search.js +117 -0
  147. package/dist/servertool/server-side-tools.d.ts +0 -1
  148. package/dist/servertool/server-side-tools.js +4 -3
  149. package/dist/sse/sse-to-json/builders/response-builder.js +16 -0
  150. package/dist/sse/sse-to-json/chat-sse-to-json-converter.d.ts +1 -0
  151. package/dist/sse/sse-to-json/chat-sse-to-json-converter.js +110 -37
  152. package/dist/telemetry/stats-center.d.ts +9 -0
  153. package/dist/telemetry/stats-center.js +29 -1
  154. package/dist/tools/apply-patch/structured/coercion.js +3 -11
  155. package/dist/tools/exec-command/validator.d.ts +1 -0
  156. package/dist/tools/exec-command/validator.js +132 -0
  157. package/dist/tools/tool-registry.d.ts +1 -0
  158. package/dist/tools/tool-registry.js +1 -1
  159. package/package.json +1 -1
@@ -0,0 +1,179 @@
1
+ import { createHash } from 'node:crypto';
2
+ import { extractMessageText, normalizeText, normalizeWhitespace } from './text-utils.js';
3
+ function stableStringifyForObservation(value) {
4
+ if (value === null)
5
+ return 'null';
6
+ const type = typeof value;
7
+ if (type === 'string')
8
+ return JSON.stringify(value);
9
+ if (type === 'number')
10
+ return Number.isFinite(value) ? String(value) : 'null';
11
+ if (type === 'boolean')
12
+ return value ? 'true' : 'false';
13
+ if (type === 'undefined' || type === 'function' || type === 'symbol')
14
+ return 'null';
15
+ if (Array.isArray(value)) {
16
+ return `[${value.map((item) => stableStringifyForObservation(item)).join(',')}]`;
17
+ }
18
+ if (value && typeof value === 'object') {
19
+ const record = value;
20
+ const keys = Object.keys(record).sort();
21
+ const chunks = [];
22
+ for (const key of keys) {
23
+ const child = record[key];
24
+ if (typeof child === 'undefined') {
25
+ continue;
26
+ }
27
+ chunks.push(`${JSON.stringify(key)}:${stableStringifyForObservation(child)}`);
28
+ }
29
+ return `{${chunks.join(',')}}`;
30
+ }
31
+ try {
32
+ return JSON.stringify(value);
33
+ }
34
+ catch {
35
+ return 'null';
36
+ }
37
+ }
38
+ function normalizeToolArgumentsForObservation(value) {
39
+ if (typeof value === 'string') {
40
+ const trimmed = value.trim();
41
+ if (!trimmed) {
42
+ return '{}';
43
+ }
44
+ if (trimmed.startsWith('{') || trimmed.startsWith('[')) {
45
+ try {
46
+ return stableStringifyForObservation(JSON.parse(trimmed));
47
+ }
48
+ catch {
49
+ return normalizeWhitespace(trimmed);
50
+ }
51
+ }
52
+ return normalizeWhitespace(trimmed);
53
+ }
54
+ if (typeof value === 'undefined') {
55
+ return '{}';
56
+ }
57
+ return stableStringifyForObservation(value);
58
+ }
59
+ function extractCommandSignaturesFromText(text) {
60
+ const signatures = [];
61
+ const bashRegex = /(?:^|\n)\s*Bash\(([^)\n]{1,1200})\)/g;
62
+ let bashMatch;
63
+ while ((bashMatch = bashRegex.exec(text)) !== null) {
64
+ const command = normalizeWhitespace((bashMatch[1] || '').trim());
65
+ if (!command)
66
+ continue;
67
+ signatures.push(`text.bash(${command})`);
68
+ }
69
+ const shellCommandRegex = /"name"\s*:\s*"shell_command"[\s\S]{0,800}?"command"\s*:\s*"([^"\\]*(?:\\.[^"\\]*)*)"/g;
70
+ let shellCommandMatch;
71
+ while ((shellCommandMatch = shellCommandRegex.exec(text)) !== null) {
72
+ const raw = shellCommandMatch[1] || '';
73
+ const command = normalizeWhitespace(raw.replace(/\\"/g, '"').replace(/\\n/g, ' ').trim());
74
+ if (!command)
75
+ continue;
76
+ signatures.push(`text.shell_command(${command})`);
77
+ }
78
+ const xmlCommandRegex = /<parameter\s+name="command">([\s\S]{1,1200}?)<\/parameter>/g;
79
+ let xmlCommandMatch;
80
+ while ((xmlCommandMatch = xmlCommandRegex.exec(text)) !== null) {
81
+ const command = normalizeWhitespace((xmlCommandMatch[1] || '').trim());
82
+ if (!command)
83
+ continue;
84
+ signatures.push(`text.param_command(${command})`);
85
+ }
86
+ return signatures;
87
+ }
88
+ function extractToolCallSignatureText(record) {
89
+ const signatures = [];
90
+ const appendSignature = (nameValue, argsValue) => {
91
+ const name = normalizeText(nameValue).toLowerCase();
92
+ if (!name) {
93
+ return;
94
+ }
95
+ const args = normalizeToolArgumentsForObservation(argsValue);
96
+ signatures.push(`${name}(${args})`);
97
+ };
98
+ const scan = (node) => {
99
+ if (!node) {
100
+ return;
101
+ }
102
+ if (Array.isArray(node)) {
103
+ for (const item of node) {
104
+ scan(item);
105
+ }
106
+ return;
107
+ }
108
+ if (typeof node !== 'object') {
109
+ return;
110
+ }
111
+ const current = node;
112
+ if (current.function && typeof current.function === 'object' && !Array.isArray(current.function)) {
113
+ const fn = current.function;
114
+ appendSignature(fn.name, fn.arguments);
115
+ }
116
+ if (normalizeText(current.type).toLowerCase() === 'function_call') {
117
+ appendSignature(current.name, current.arguments);
118
+ }
119
+ if (typeof current.name === 'string' && Object.prototype.hasOwnProperty.call(current, 'arguments')) {
120
+ appendSignature(current.name, current.arguments);
121
+ }
122
+ if (current.function_call && typeof current.function_call === 'object' && !Array.isArray(current.function_call)) {
123
+ const fnCall = current.function_call;
124
+ appendSignature(fnCall.name, fnCall.arguments);
125
+ }
126
+ };
127
+ scan(record.tool_calls);
128
+ scan(record.tool_call);
129
+ scan(record.function_call);
130
+ scan(record.output);
131
+ const textPayload = extractMessageText(record.content || record.output || record.input || '');
132
+ if (textPayload) {
133
+ signatures.push(...extractCommandSignaturesFromText(textPayload));
134
+ }
135
+ return signatures.join('; ');
136
+ }
137
+ function extractToolSignatureForHash(message) {
138
+ if (!message || typeof message !== 'object' || Array.isArray(message)) {
139
+ return '';
140
+ }
141
+ const record = message;
142
+ return extractToolCallSignatureText(record);
143
+ }
144
+ function normalizeMessageForHash(message) {
145
+ if (!message || typeof message !== 'object' || Array.isArray(message)) {
146
+ return '';
147
+ }
148
+ const record = message;
149
+ const role = normalizeText(record.role).toLowerCase() || 'unknown';
150
+ const text = extractMessageText(record.content || record.output || record.input || '');
151
+ const toolSignature = extractToolCallSignatureText(record);
152
+ const combined = [text, toolSignature].filter((entry) => typeof entry === 'string' && entry.trim()).join(' | ');
153
+ if (!combined) {
154
+ return role;
155
+ }
156
+ return `${role}:${combined.slice(0, 800)}`;
157
+ }
158
+ export function buildObservationHash(messages) {
159
+ const tail = messages
160
+ .slice(-20)
161
+ .map((message) => normalizeMessageForHash(message))
162
+ .filter(Boolean)
163
+ .join('\n');
164
+ if (!tail) {
165
+ return 'empty';
166
+ }
167
+ return createHash('sha1').update(tail).digest('hex').slice(0, 16);
168
+ }
169
+ export function buildToolSignatureHash(messages) {
170
+ const signatures = messages
171
+ .slice(-20)
172
+ .map((message) => extractToolSignatureForHash(message))
173
+ .filter(Boolean)
174
+ .join('\n');
175
+ if (!signatures) {
176
+ return undefined;
177
+ }
178
+ return createHash('sha1').update(signatures).digest('hex').slice(0, 16);
179
+ }
@@ -0,0 +1,4 @@
1
+ import type { StageTemplateBundle } from './types.js';
2
+ export declare function buildStageMessage(template: string, baseText: string): string;
3
+ export declare function resolveStageTemplates(mode: 'auto' | 'on'): StageTemplateBundle;
4
+ export declare function resolveStageMode(modeFromState: unknown): 'auto' | 'on' | 'off';
@@ -0,0 +1,96 @@
1
+ import { loadStopMessageStageTemplate } from '../../../router/virtual-router/stop-message-stage-template-files.js';
2
+ import { normalizeStageMode, normalizeText } from './text-utils.js';
3
+ const DEFAULT_STATUS_TEMPLATE = [
4
+ '请围绕当前目标直接推进,不要陷入任务面板操作:',
5
+ '1) 优先完成一个可验证动作(改代码 / 补测试 / 运行验证);',
6
+ '2) 若确实缺少目标或上下文,再一次性补齐必要信息,不要循环轮询;',
7
+ '3) 仅在动作完成或出现阻塞时,同步记录;',
8
+ '4) 若执行受阻,输出结构化阻塞信息(见下方约束)以便系统建单。',
9
+ '',
10
+ '{{BASE_STOP_MESSAGE}}'
11
+ ].join('\n');
12
+ const DEFAULT_ACTIVE_TEMPLATE = [
13
+ '检测到当前任务可继续,请直接推进工程动作:',
14
+ '1) 先做实现/修复/验证,不要把任务管理操作当作主要步骤;',
15
+ '2) 可以调用工具执行代码与验证,避免空状态播报;',
16
+ '3) 若阻塞,请明确 blocker 并给出 next_action,必要时按结构化格式输出。',
17
+ '',
18
+ '{{BASE_STOP_MESSAGE}}'
19
+ ].join('\n');
20
+ const DEFAULT_LOOP_TEMPLATE = [
21
+ '检测到可能出现重复循环,请先自检并尝试跳出:',
22
+ '1) 对比最近两轮是否重复同一工具调用+参数(包括文本里的命令参数);',
23
+ '2) 若重复,改做新的有效动作(改代码、跑测试、定位错误);',
24
+ '3) 执行后再观察状态变化;若仍无变化则停止并报告具体阻塞点。',
25
+ '',
26
+ '{{BASE_STOP_MESSAGE}}'
27
+ ].join('\n');
28
+ const DEFAULT_NO_TASK_SUMMARY_TEMPLATE = [
29
+ '当前未发现可推进任务。',
30
+ '请只输出一次收尾总结;不要继续轮询任务列表。',
31
+ '若存在阻塞,请输出一个 JSON 对象(不要附加解释文本):',
32
+ '{"type":"blocked","summary":"...","blocker":"...","impact":"...","next_action":"...","evidence":["..."]}',
33
+ '',
34
+ '{{BASE_STOP_MESSAGE}}'
35
+ ].join('\n');
36
+ export function buildStageMessage(template, baseText) {
37
+ const safeBaseText = baseText.trim();
38
+ const safeTemplate = typeof template === 'string' ? template.trim() : '';
39
+ if (safeTemplate.includes('{{BASE_STOP_MESSAGE}}')) {
40
+ const replaced = safeTemplate.replaceAll('{{BASE_STOP_MESSAGE}}', safeBaseText).replace(/\n{3,}/g, '\n\n').trim();
41
+ if (replaced) {
42
+ return replaced;
43
+ }
44
+ }
45
+ if (!safeTemplate) {
46
+ return safeBaseText;
47
+ }
48
+ if (!safeBaseText) {
49
+ return safeTemplate;
50
+ }
51
+ return `${safeTemplate}\n\n原始约束:\n${safeBaseText}`.trim();
52
+ }
53
+ function loadStageTemplate(stage) {
54
+ const loaded = loadStopMessageStageTemplate(stage);
55
+ return loaded.text || null;
56
+ }
57
+ export function resolveStageTemplates(mode) {
58
+ const statusProbeTemplate = loadStageTemplate('status_probe');
59
+ const activeContinueTemplate = loadStageTemplate('active_continue');
60
+ const loopSelfCheckTemplate = loadStageTemplate('loop_self_check');
61
+ const hasUserTemplate = Boolean(statusProbeTemplate || activeContinueTemplate || loopSelfCheckTemplate);
62
+ const enabled = mode === 'on' || hasUserTemplate;
63
+ if (!enabled) {
64
+ return {
65
+ enabled: false,
66
+ statusProbeTemplate: '',
67
+ activeContinueTemplate: '',
68
+ loopSelfCheckTemplate: '',
69
+ noTaskSummaryTemplate: DEFAULT_NO_TASK_SUMMARY_TEMPLATE
70
+ };
71
+ }
72
+ return {
73
+ enabled: true,
74
+ statusProbeTemplate: statusProbeTemplate || DEFAULT_STATUS_TEMPLATE,
75
+ activeContinueTemplate: activeContinueTemplate || DEFAULT_ACTIVE_TEMPLATE,
76
+ loopSelfCheckTemplate: loopSelfCheckTemplate || DEFAULT_LOOP_TEMPLATE,
77
+ noTaskSummaryTemplate: DEFAULT_NO_TASK_SUMMARY_TEMPLATE
78
+ };
79
+ }
80
+ export function resolveStageMode(modeFromState) {
81
+ const stateMode = normalizeStageMode(modeFromState);
82
+ if (stateMode) {
83
+ return stateMode;
84
+ }
85
+ const raw = normalizeText(process.env.ROUTECODEX_STOPMESSAGE_STAGE_MODE).toLowerCase();
86
+ if (raw === '1' || raw === 'true' || raw === 'on') {
87
+ return 'on';
88
+ }
89
+ if (raw === '0' || raw === 'false' || raw === 'off') {
90
+ return 'off';
91
+ }
92
+ if (raw === 'auto') {
93
+ return 'auto';
94
+ }
95
+ return 'auto';
96
+ }
@@ -0,0 +1,9 @@
1
+ import type { StopMessageBdWorkState, StopMessageStageName } from './types.js';
2
+ export declare function normalizeWhitespace(text: string): string;
3
+ export declare function normalizeText(value: unknown): string;
4
+ export declare function extractMessageText(value: unknown): string;
5
+ export declare function normalizeMessageForHeuristics(message: unknown): string;
6
+ export declare function normalizeStageName(value: unknown): StopMessageStageName | undefined;
7
+ export declare function normalizeBdWorkState(value: unknown): StopMessageBdWorkState | undefined;
8
+ export declare function normalizeStageMode(value: unknown): 'on' | 'off' | 'auto' | undefined;
9
+ export declare function toSafeInt(value: unknown, fallback: number): number;
@@ -0,0 +1,89 @@
1
+ export function normalizeWhitespace(text) {
2
+ return text.replace(/\s+/g, ' ').trim();
3
+ }
4
+ export function normalizeText(value) {
5
+ return typeof value === 'string' ? value.trim() : '';
6
+ }
7
+ export function extractMessageText(value) {
8
+ if (typeof value === 'string') {
9
+ return normalizeWhitespace(value);
10
+ }
11
+ if (Array.isArray(value)) {
12
+ const chunks = [];
13
+ for (const entry of value) {
14
+ const text = extractMessageText(entry);
15
+ if (text) {
16
+ chunks.push(text);
17
+ }
18
+ }
19
+ return normalizeWhitespace(chunks.join('\n'));
20
+ }
21
+ if (!value || typeof value !== 'object') {
22
+ return '';
23
+ }
24
+ const record = value;
25
+ const candidates = [
26
+ record.text,
27
+ record.content,
28
+ record.output_text,
29
+ record.input_text,
30
+ record.arguments,
31
+ record.name,
32
+ record.result,
33
+ record.stdout,
34
+ record.stderr
35
+ ];
36
+ const chunks = [];
37
+ for (const candidate of candidates) {
38
+ const text = extractMessageText(candidate);
39
+ if (text) {
40
+ chunks.push(text);
41
+ }
42
+ }
43
+ return normalizeWhitespace(chunks.join('\n'));
44
+ }
45
+ export function normalizeMessageForHeuristics(message) {
46
+ if (!message || typeof message !== 'object' || Array.isArray(message)) {
47
+ return '';
48
+ }
49
+ const record = message;
50
+ const role = normalizeText(record.role).toLowerCase();
51
+ const text = extractMessageText(record.content || record.output || record.input || '');
52
+ return `${role}:${text}`.trim();
53
+ }
54
+ export function normalizeStageName(value) {
55
+ if (typeof value !== 'string') {
56
+ return undefined;
57
+ }
58
+ const normalized = value.trim().toLowerCase();
59
+ if (normalized === 'status_probe' || normalized === 'active_continue' || normalized === 'loop_self_check') {
60
+ return normalized;
61
+ }
62
+ return undefined;
63
+ }
64
+ export function normalizeBdWorkState(value) {
65
+ if (typeof value !== 'string') {
66
+ return undefined;
67
+ }
68
+ const normalized = value.trim().toLowerCase();
69
+ if (normalized === 'active' || normalized === 'idle' || normalized === 'unknown') {
70
+ return normalized;
71
+ }
72
+ return undefined;
73
+ }
74
+ export function normalizeStageMode(value) {
75
+ if (typeof value !== 'string') {
76
+ return undefined;
77
+ }
78
+ const normalized = value.trim().toLowerCase();
79
+ if (normalized === 'on' || normalized === 'off' || normalized === 'auto') {
80
+ return normalized;
81
+ }
82
+ return undefined;
83
+ }
84
+ export function toSafeInt(value, fallback) {
85
+ if (typeof value !== 'number' || !Number.isFinite(value)) {
86
+ return fallback;
87
+ }
88
+ return Math.max(0, Math.floor(value));
89
+ }
@@ -0,0 +1,59 @@
1
+ export type StopMessageStageName = 'status_probe' | 'active_continue' | 'loop_self_check';
2
+ export type StopMessageBdWorkState = 'active' | 'idle' | 'unknown';
3
+ export type StopMessageBdMode = 'auto' | 'runtime' | 'heuristic';
4
+ export type StopMessageBdTaskSource = 'in_progress' | 'ready' | 'open';
5
+ export interface StopMessageStageStateSnapshot {
6
+ stopMessageStage?: string;
7
+ stopMessageStageMode?: 'on' | 'off' | 'auto' | string;
8
+ stopMessageObservationHash?: string;
9
+ stopMessageObservationStableCount?: number;
10
+ stopMessageBdWorkState?: string;
11
+ stopMessageNoTaskSummaryUsed?: boolean;
12
+ }
13
+ export interface StopMessageBdCommandResult {
14
+ status: number | null;
15
+ stdout: string;
16
+ stderr: string;
17
+ error?: unknown;
18
+ }
19
+ export type StopMessageBdCommandRunner = (args: string[], options: {
20
+ cwd: string;
21
+ timeoutMs: number;
22
+ }) => StopMessageBdCommandResult;
23
+ export interface StopMessageStageDecision {
24
+ action: 'followup' | 'stop';
25
+ stage?: StopMessageStageName;
26
+ followupText?: string;
27
+ observationHash: string;
28
+ observationStableCount: number;
29
+ toolSignatureHash?: string;
30
+ bdWorkState: StopMessageBdWorkState;
31
+ assignedIssueId?: string;
32
+ assignedIssueTitle?: string;
33
+ assignedIssueSource?: StopMessageBdTaskSource;
34
+ noTaskSummaryUsed?: boolean;
35
+ stopReason?: 'loop_stable' | 'bd_idle' | 'mode_off' | 'no_task_after_summary';
36
+ }
37
+ export interface StopMessageBdTaskSelection {
38
+ issueId: string;
39
+ issueTitle: string;
40
+ priority: number;
41
+ source: StopMessageBdTaskSource;
42
+ }
43
+ export interface StopMessageBdTaskProbeResult {
44
+ status: 'ok' | 'unknown';
45
+ task?: StopMessageBdTaskSelection;
46
+ }
47
+ export interface StageTemplateBundle {
48
+ enabled: boolean;
49
+ statusProbeTemplate: string;
50
+ activeContinueTemplate: string;
51
+ loopSelfCheckTemplate: string;
52
+ noTaskSummaryTemplate: string;
53
+ }
54
+ export interface BdRuntimeCacheEntry {
55
+ mode: StopMessageBdMode;
56
+ cwd: string;
57
+ expiresAt: number;
58
+ state: StopMessageBdWorkState;
59
+ }
@@ -1,43 +1,3 @@
1
- export type StopMessageStageName = 'status_probe' | 'active_continue' | 'loop_self_check';
2
- export type StopMessageBdWorkState = 'active' | 'idle' | 'unknown';
3
- export type StopMessageBdMode = 'auto' | 'runtime' | 'heuristic';
4
- export interface StopMessageStageStateSnapshot {
5
- stopMessageStage?: string;
6
- stopMessageStageMode?: 'on' | 'off' | 'auto' | string;
7
- stopMessageObservationHash?: string;
8
- stopMessageObservationStableCount?: number;
9
- stopMessageBdWorkState?: string;
10
- }
11
- export interface StopMessageBdCommandResult {
12
- status: number | null;
13
- stdout: string;
14
- stderr: string;
15
- error?: unknown;
16
- }
17
- export type StopMessageBdCommandRunner = (args: string[], options: {
18
- cwd: string;
19
- timeoutMs: number;
20
- }) => StopMessageBdCommandResult;
21
- export interface StopMessageStageDecision {
22
- action: 'followup' | 'stop';
23
- stage?: StopMessageStageName;
24
- followupText?: string;
25
- observationHash: string;
26
- observationStableCount: number;
27
- toolSignatureHash?: string;
28
- bdWorkState: StopMessageBdWorkState;
29
- stopReason?: 'loop_stable' | 'bd_idle' | 'mode_off';
30
- }
31
- export declare function resolveStopMessageStageDecision(args: {
32
- baseText: string;
33
- state: StopMessageStageStateSnapshot;
34
- capturedMessages: unknown[];
35
- bdCommandRunner?: StopMessageBdCommandRunner;
36
- nowMs?: number;
37
- }): StopMessageStageDecision;
38
- export declare function resolveBdWorkStateFromRuntime(options?: {
39
- bdCommandRunner?: StopMessageBdCommandRunner;
40
- nowMs?: number;
41
- cwd?: string;
42
- }): StopMessageBdWorkState;
43
- export declare function resetStopMessageBdRuntimeCacheForTests(): void;
1
+ export type { StopMessageBdCommandResult, StopMessageBdCommandRunner, StopMessageBdMode, StopMessageBdTaskSelection, StopMessageBdTaskSource, StopMessageBdWorkState, StopMessageStageDecision, StopMessageStageName, StopMessageStageStateSnapshot } from './stop-message-stage-policy/types.js';
2
+ export { resolveStopMessageStageDecision } from './stop-message-stage-policy/decision.js';
3
+ export { resetStopMessageBdRuntimeCacheForTests, resolveBdTaskSelectionFromRuntime, resolveBdWorkStateFromRuntime } from './stop-message-stage-policy/bd-runtime.js';