@jsonstudio/llms 0.6.1739 → 0.6.1890
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/compat/actions/deepseek-web-request.d.ts +3 -0
- package/dist/conversion/compat/actions/deepseek-web-request.js +350 -0
- package/dist/conversion/compat/actions/deepseek-web-response.d.ts +3 -0
- package/dist/conversion/compat/actions/deepseek-web-response.js +886 -0
- package/dist/conversion/compat/actions/gemini-cli-request.js +3 -1
- package/dist/conversion/compat/profiles/chat-deepseek-web.json +18 -0
- package/dist/conversion/hub/operation-table/semantic-mappers/anthropic-mapper.js +166 -2
- package/dist/conversion/hub/operation-table/semantic-mappers/gemini-mapper.js +169 -0
- package/dist/conversion/hub/operation-table/semantic-mappers/responses-mapper.js +6 -0
- package/dist/conversion/hub/pipeline/compat/compat-pipeline-executor.js +12 -0
- package/dist/conversion/hub/pipeline/compat/compat-profile-resolver.js +1 -0
- package/dist/conversion/hub/pipeline/compat/compat-types.d.ts +4 -0
- package/dist/conversion/hub/pipeline/hub-pipeline.js +365 -144
- package/dist/conversion/hub/pipeline/stages/resp_outbound/resp_outbound_stage1_client_remap/index.js +9 -0
- package/dist/conversion/hub/policy/policy-engine.d.ts +2 -0
- package/dist/conversion/hub/policy/policy-engine.js +8 -0
- package/dist/conversion/hub/process/chat-process.js +466 -16
- package/dist/conversion/hub/response/provider-response.js +0 -35
- package/dist/conversion/responses/responses-openai-bridge.d.ts +2 -0
- package/dist/conversion/responses/responses-openai-bridge.js +166 -8
- package/dist/conversion/shared/anthropic-message-utils.js +10 -1
- package/dist/conversion/shared/protocol-field-allowlists.d.ts +2 -2
- package/dist/conversion/shared/protocol-field-allowlists.js +4 -0
- package/dist/conversion/shared/tool-governor.js +102 -0
- package/dist/guidance/index.js +17 -0
- package/dist/router/virtual-router/bootstrap.js +46 -1
- package/dist/router/virtual-router/classifier.js +59 -4
- package/dist/router/virtual-router/engine/health/index.js +6 -6
- package/dist/router/virtual-router/engine/routing-state/store.js +16 -3
- package/dist/router/virtual-router/engine-logging.js +62 -24
- package/dist/router/virtual-router/engine-selection/route-utils.js +20 -20
- package/dist/router/virtual-router/engine-selection/tier-selection.js +2 -2
- package/dist/router/virtual-router/engine.d.ts +3 -1
- package/dist/router/virtual-router/engine.js +359 -39
- package/dist/router/virtual-router/features.js +2 -1
- package/dist/router/virtual-router/pre-command-file-resolver.d.ts +2 -0
- package/dist/router/virtual-router/pre-command-file-resolver.js +90 -0
- package/dist/router/virtual-router/provider-registry.js +3 -1
- package/dist/router/virtual-router/routing-instructions.d.ts +15 -1
- package/dist/router/virtual-router/routing-instructions.js +110 -151
- package/dist/router/virtual-router/routing-pre-command-actions.d.ts +3 -0
- package/dist/router/virtual-router/routing-pre-command-actions.js +26 -0
- package/dist/router/virtual-router/routing-pre-command-parser.d.ts +2 -0
- package/dist/router/virtual-router/routing-pre-command-parser.js +85 -0
- package/dist/router/virtual-router/routing-pre-command-state-codec.d.ts +3 -0
- package/dist/router/virtual-router/routing-pre-command-state-codec.js +24 -0
- package/dist/router/virtual-router/routing-stop-message-actions.d.ts +2 -0
- package/dist/router/virtual-router/routing-stop-message-actions.js +96 -0
- package/dist/router/virtual-router/routing-stop-message-parser.d.ts +3 -0
- package/dist/router/virtual-router/routing-stop-message-parser.js +142 -0
- package/dist/router/virtual-router/routing-stop-message-state-codec.d.ts +4 -0
- package/dist/router/virtual-router/routing-stop-message-state-codec.js +85 -0
- package/dist/router/virtual-router/sticky-session-store.js +206 -57
- package/dist/router/virtual-router/stop-message-stage-template-files.d.ts +12 -0
- package/dist/router/virtual-router/stop-message-stage-template-files.js +67 -0
- package/dist/router/virtual-router/stop-message-state-sync.d.ts +1 -1
- package/dist/router/virtual-router/stop-message-state-sync.js +5 -0
- package/dist/router/virtual-router/token-file-scanner.d.ts +9 -0
- package/dist/router/virtual-router/token-file-scanner.js +64 -3
- package/dist/router/virtual-router/tool-signals.d.ts +5 -0
- package/dist/router/virtual-router/tool-signals.js +42 -3
- package/dist/router/virtual-router/types.d.ts +19 -1
- package/dist/router/virtual-router/types.js +1 -0
- package/dist/servertool/clock/config.d.ts +1 -1
- package/dist/servertool/clock/config.js +27 -4
- package/dist/servertool/clock/state.js +41 -2
- package/dist/servertool/clock/task-store.d.ts +2 -2
- package/dist/servertool/clock/task-store.js +1 -1
- package/dist/servertool/clock/tasks.d.ts +3 -1
- package/dist/servertool/clock/tasks.js +209 -18
- package/dist/servertool/clock/types.d.ts +17 -0
- package/dist/servertool/continue-execution/log.d.ts +3 -0
- package/dist/servertool/continue-execution/log.js +13 -0
- package/dist/servertool/engine.js +414 -68
- package/dist/servertool/handlers/antigravity-thought-signature-bootstrap.js +6 -6
- package/dist/servertool/handlers/clock-auto.js +54 -71
- package/dist/servertool/handlers/clock.js +121 -6
- package/dist/servertool/handlers/continue-execution.d.ts +1 -0
- package/dist/servertool/handlers/continue-execution.js +91 -0
- package/dist/servertool/handlers/followup-request-builder.js +13 -0
- package/dist/servertool/handlers/gemini-empty-reply-continue.js +1 -1
- package/dist/servertool/handlers/iflow-model-error-retry.js +1 -1
- package/dist/servertool/handlers/recursive-detection-guard.js +1 -1
- package/dist/servertool/handlers/stop-message-auto.js +386 -257
- package/dist/servertool/handlers/stop-message-stage-policy.d.ts +43 -0
- package/dist/servertool/handlers/stop-message-stage-policy.js +684 -0
- package/dist/servertool/handlers/vision.js +1 -1
- package/dist/servertool/log/progress-file.d.ts +14 -0
- package/dist/servertool/log/progress-file.js +88 -0
- package/dist/servertool/pre-command-hooks.d.ts +17 -0
- package/dist/servertool/pre-command-hooks.js +491 -0
- package/dist/servertool/registry.d.ts +23 -6
- package/dist/servertool/registry.js +66 -1
- package/dist/servertool/server-side-tools.d.ts +1 -0
- package/dist/servertool/server-side-tools.js +216 -14
- package/dist/servertool/stop-gateway-context.d.ts +14 -0
- package/dist/servertool/stop-gateway-context.js +167 -0
- package/dist/servertool/stop-message-compare-context.d.ts +24 -0
- package/dist/servertool/stop-message-compare-context.js +133 -0
- package/dist/servertool/types.d.ts +12 -0
- package/dist/sse/sse-to-json/anthropic-sse-to-json-converter.d.ts +1 -0
- package/dist/sse/sse-to-json/anthropic-sse-to-json-converter.js +36 -1
- package/dist/sse/sse-to-json/builders/anthropic-response-builder.js +3 -0
- package/dist/sse/sse-to-json/chat-sse-to-json-converter.d.ts +3 -0
- package/dist/sse/sse-to-json/chat-sse-to-json-converter.js +118 -1
- package/dist/tools/apply-patch/args-normalizer/default-actions.js +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export type StopMessageStageTemplateName = 'status_probe' | 'active_continue' | 'loop_self_check';
|
|
2
|
+
export interface StopMessageStageTemplateLoadResult {
|
|
3
|
+
stage: StopMessageStageTemplateName;
|
|
4
|
+
ref: string;
|
|
5
|
+
text?: string;
|
|
6
|
+
error?: string;
|
|
7
|
+
}
|
|
8
|
+
export declare function loadStopMessageStageTemplate(stage: StopMessageStageTemplateName): StopMessageStageTemplateLoadResult;
|
|
9
|
+
export declare function validateStopMessageStageTemplatesCompleteness(): {
|
|
10
|
+
ok: boolean;
|
|
11
|
+
missing: StopMessageStageTemplateLoadResult[];
|
|
12
|
+
};
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { resolveStopMessageText } from './stop-message-file-resolver.js';
|
|
2
|
+
const DEFAULT_STAGE_TEMPLATE_REFS = {
|
|
3
|
+
status_probe: '<file://stopMessage/stage-status-check.md>',
|
|
4
|
+
active_continue: '<file://stopMessage/stage-active-continue.md>',
|
|
5
|
+
loop_self_check: '<file://stopMessage/stage-loop-self-check.md>'
|
|
6
|
+
};
|
|
7
|
+
const STAGE_ENV_KEYS = {
|
|
8
|
+
status_probe: 'ROUTECODEX_STOPMESSAGE_STAGE_STATUS_REF',
|
|
9
|
+
active_continue: 'ROUTECODEX_STOPMESSAGE_STAGE_ACTIVE_REF',
|
|
10
|
+
loop_self_check: 'ROUTECODEX_STOPMESSAGE_STAGE_LOOP_REF'
|
|
11
|
+
};
|
|
12
|
+
export function loadStopMessageStageTemplate(stage) {
|
|
13
|
+
const ref = resolveStopMessageStageTemplateRef(stage);
|
|
14
|
+
if (!ref) {
|
|
15
|
+
return {
|
|
16
|
+
stage,
|
|
17
|
+
ref: '',
|
|
18
|
+
error: `missing template reference for ${stage}`
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
try {
|
|
22
|
+
const text = resolveStopMessageText(ref);
|
|
23
|
+
const normalized = typeof text === 'string' ? text.trim() : '';
|
|
24
|
+
if (!normalized) {
|
|
25
|
+
return {
|
|
26
|
+
stage,
|
|
27
|
+
ref,
|
|
28
|
+
error: `template is empty for ${stage}`
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
return {
|
|
32
|
+
stage,
|
|
33
|
+
ref,
|
|
34
|
+
text: normalized
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
catch (error) {
|
|
38
|
+
const message = error instanceof Error ? error.message : String(error ?? 'unknown error');
|
|
39
|
+
return {
|
|
40
|
+
stage,
|
|
41
|
+
ref,
|
|
42
|
+
error: message
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
export function validateStopMessageStageTemplatesCompleteness() {
|
|
47
|
+
const requiredStages = ['status_probe', 'active_continue', 'loop_self_check'];
|
|
48
|
+
const missing = [];
|
|
49
|
+
for (const stage of requiredStages) {
|
|
50
|
+
const loaded = loadStopMessageStageTemplate(stage);
|
|
51
|
+
if (!loaded.text) {
|
|
52
|
+
missing.push(loaded);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return {
|
|
56
|
+
ok: missing.length === 0,
|
|
57
|
+
missing
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
function resolveStopMessageStageTemplateRef(stage) {
|
|
61
|
+
const envKey = STAGE_ENV_KEYS[stage];
|
|
62
|
+
const envRef = normalizeText(process.env[envKey]);
|
|
63
|
+
return envRef || DEFAULT_STAGE_TEMPLATE_REFS[stage];
|
|
64
|
+
}
|
|
65
|
+
function normalizeText(value) {
|
|
66
|
+
return typeof value === 'string' ? value.trim() : '';
|
|
67
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { RoutingInstructionState } from './routing-instructions.js';
|
|
2
|
-
type StopMessageSubset = Pick<RoutingInstructionState, 'stopMessageSource' | 'stopMessageText' | 'stopMessageMaxRepeats' | 'stopMessageUsed' | 'stopMessageUpdatedAt' | 'stopMessageLastUsedAt'>;
|
|
2
|
+
type StopMessageSubset = Pick<RoutingInstructionState, 'stopMessageSource' | 'stopMessageText' | 'stopMessageMaxRepeats' | 'stopMessageUsed' | 'stopMessageStage' | 'stopMessageStageMode' | 'stopMessageObservationHash' | 'stopMessageObservationStableCount' | 'stopMessageBdWorkState' | 'stopMessageUpdatedAt' | 'stopMessageLastUsedAt'>;
|
|
3
3
|
/**
|
|
4
4
|
* Decide whether we should overwrite in-memory stopMessage fields with persisted ones.
|
|
5
5
|
*
|
|
@@ -41,6 +41,11 @@ export function mergeStopMessageFromPersisted(existing, persisted) {
|
|
|
41
41
|
stopMessageText: persisted.stopMessageText,
|
|
42
42
|
stopMessageMaxRepeats: persisted.stopMessageMaxRepeats,
|
|
43
43
|
stopMessageUsed: persisted.stopMessageUsed,
|
|
44
|
+
stopMessageStage: persisted.stopMessageStage,
|
|
45
|
+
stopMessageStageMode: persisted.stopMessageStageMode,
|
|
46
|
+
stopMessageObservationHash: persisted.stopMessageObservationHash,
|
|
47
|
+
stopMessageObservationStableCount: persisted.stopMessageObservationStableCount,
|
|
48
|
+
stopMessageBdWorkState: persisted.stopMessageBdWorkState,
|
|
44
49
|
stopMessageUpdatedAt: persisted.stopMessageUpdatedAt,
|
|
45
50
|
stopMessageLastUsedAt: persisted.stopMessageLastUsedAt
|
|
46
51
|
};
|
|
@@ -13,3 +13,12 @@ export interface OAuthTokenFileMatch {
|
|
|
13
13
|
* 仅在 Node 环境下使用;如果环境不满足,返回空列表。
|
|
14
14
|
*/
|
|
15
15
|
export declare function scanOAuthTokenFiles(oauthProviderId: string, authDir?: string): OAuthTokenFileMatch[];
|
|
16
|
+
/**
|
|
17
|
+
* 扫描 DeepSeek account token 文件。
|
|
18
|
+
*
|
|
19
|
+
* 约定:
|
|
20
|
+
* - 目录: ~/.routecodex/auth
|
|
21
|
+
* - 文件名: deepseek-account-<alias>.json
|
|
22
|
+
* 例如: deepseek-account-1.json, deepseek-account-2-work.json
|
|
23
|
+
*/
|
|
24
|
+
export declare function scanDeepSeekAccountTokenFiles(authDir?: string): OAuthTokenFileMatch[];
|
|
@@ -2,6 +2,17 @@ import fs from 'fs';
|
|
|
2
2
|
import path from 'path';
|
|
3
3
|
import os from 'os';
|
|
4
4
|
const TOKEN_FILE_PATTERN = /^([a-z0-9_-]+)-oauth-(\d+)(?:-(.+))?\.json$/i;
|
|
5
|
+
const DEEPSEEK_ACCOUNT_TOKEN_PATTERN = /^deepseek-account-(.+)\.json$/i;
|
|
6
|
+
function resolveAuthDir(authDir) {
|
|
7
|
+
if (authDir && authDir.trim()) {
|
|
8
|
+
return authDir.trim();
|
|
9
|
+
}
|
|
10
|
+
const envDir = (process.env.ROUTECODEX_AUTH_DIR || process.env.RCC_AUTH_DIR || '').trim();
|
|
11
|
+
if (envDir) {
|
|
12
|
+
return envDir;
|
|
13
|
+
}
|
|
14
|
+
return path.join(os.homedir(), '.routecodex', 'auth');
|
|
15
|
+
}
|
|
5
16
|
/**
|
|
6
17
|
* 扫描本地 RouteCodex auth 目录中的 OAuth token 文件。
|
|
7
18
|
*
|
|
@@ -19,9 +30,7 @@ export function scanOAuthTokenFiles(oauthProviderId, authDir) {
|
|
|
19
30
|
if (!provider) {
|
|
20
31
|
return [];
|
|
21
32
|
}
|
|
22
|
-
const baseDir = authDir
|
|
23
|
-
? authDir.trim()
|
|
24
|
-
: path.join(os.homedir(), '.routecodex', 'auth');
|
|
33
|
+
const baseDir = resolveAuthDir(authDir);
|
|
25
34
|
let entries;
|
|
26
35
|
try {
|
|
27
36
|
entries = fs.readdirSync(baseDir);
|
|
@@ -51,6 +60,58 @@ export function scanOAuthTokenFiles(oauthProviderId, authDir) {
|
|
|
51
60
|
matches.sort((a, b) => a.sequence - b.sequence);
|
|
52
61
|
return matches;
|
|
53
62
|
}
|
|
63
|
+
/**
|
|
64
|
+
* 扫描 DeepSeek account token 文件。
|
|
65
|
+
*
|
|
66
|
+
* 约定:
|
|
67
|
+
* - 目录: ~/.routecodex/auth
|
|
68
|
+
* - 文件名: deepseek-account-<alias>.json
|
|
69
|
+
* 例如: deepseek-account-1.json, deepseek-account-2-work.json
|
|
70
|
+
*/
|
|
71
|
+
export function scanDeepSeekAccountTokenFiles(authDir) {
|
|
72
|
+
if (!isNodeEnvironment()) {
|
|
73
|
+
return [];
|
|
74
|
+
}
|
|
75
|
+
const baseDir = resolveAuthDir(authDir);
|
|
76
|
+
let entries;
|
|
77
|
+
try {
|
|
78
|
+
entries = fs.readdirSync(baseDir);
|
|
79
|
+
}
|
|
80
|
+
catch {
|
|
81
|
+
return [];
|
|
82
|
+
}
|
|
83
|
+
const matches = [];
|
|
84
|
+
for (const entry of entries) {
|
|
85
|
+
if (!entry.endsWith('.json'))
|
|
86
|
+
continue;
|
|
87
|
+
const match = entry.match(DEEPSEEK_ACCOUNT_TOKEN_PATTERN);
|
|
88
|
+
if (!match)
|
|
89
|
+
continue;
|
|
90
|
+
const aliasRaw = (match[1] || '').trim();
|
|
91
|
+
if (!aliasRaw.length)
|
|
92
|
+
continue;
|
|
93
|
+
const numericMatch = aliasRaw.match(/^(\d+)(?:-|$)/);
|
|
94
|
+
const numericPrefix = numericMatch ? Number.parseInt(numericMatch[1], 10) : undefined;
|
|
95
|
+
matches.push({
|
|
96
|
+
filePath: path.join(baseDir, entry),
|
|
97
|
+
alias: aliasRaw,
|
|
98
|
+
...(Number.isFinite(numericPrefix) ? { numericPrefix } : {})
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
matches.sort((a, b) => {
|
|
102
|
+
const aNum = typeof a.numericPrefix === 'number' ? a.numericPrefix : Number.POSITIVE_INFINITY;
|
|
103
|
+
const bNum = typeof b.numericPrefix === 'number' ? b.numericPrefix : Number.POSITIVE_INFINITY;
|
|
104
|
+
if (aNum !== bNum) {
|
|
105
|
+
return aNum - bNum;
|
|
106
|
+
}
|
|
107
|
+
return a.alias.localeCompare(b.alias);
|
|
108
|
+
});
|
|
109
|
+
return matches.map((entry, index) => ({
|
|
110
|
+
filePath: entry.filePath,
|
|
111
|
+
sequence: index + 1,
|
|
112
|
+
alias: entry.alias
|
|
113
|
+
}));
|
|
114
|
+
}
|
|
54
115
|
function isNodeEnvironment() {
|
|
55
116
|
return typeof process !== 'undefined' && !!process.release && process.release.name === 'node';
|
|
56
117
|
}
|
|
@@ -8,6 +8,11 @@ export type ToolClassification = {
|
|
|
8
8
|
export declare function detectVisionTool(request: StandardizedRequest): boolean;
|
|
9
9
|
export declare function detectCodingTool(request: StandardizedRequest): boolean;
|
|
10
10
|
export declare function detectWebTool(request: StandardizedRequest): boolean;
|
|
11
|
+
/**
|
|
12
|
+
* Detect if a web_search tool is explicitly declared in the request tools list.
|
|
13
|
+
* This is used for routing decisions in the classifier.
|
|
14
|
+
*/
|
|
15
|
+
export declare function detectWebSearchToolDeclared(request: StandardizedRequest): boolean;
|
|
11
16
|
export declare function extractMeaningfulDeclaredToolNames(tools: StandardizedRequest['tools'] | undefined): string[];
|
|
12
17
|
export declare function detectLastAssistantToolCategory(messages: StandardizedMessage[]): ToolClassification | undefined;
|
|
13
18
|
export declare function classifyToolCallForReport(call: StandardizedMessage['tool_calls'][number]): ToolClassification | undefined;
|
|
@@ -61,6 +61,8 @@ const COMMAND_ALIASES = new Map([
|
|
|
61
61
|
['perl5', 'perl']
|
|
62
62
|
]);
|
|
63
63
|
const GIT_WRITE_SUBCOMMANDS = new Set(['add', 'commit', 'apply', 'am', 'rebase', 'checkout', 'merge']);
|
|
64
|
+
const GIT_SEARCH_SUBCOMMANDS = new Set(['grep', 'log', 'shortlog', 'reflog', 'blame']);
|
|
65
|
+
const BD_SEARCH_SUBCOMMANDS = new Set(['search']);
|
|
64
66
|
const PACKAGE_MANAGER_COMMANDS = new Map([
|
|
65
67
|
['npm', new Set(['install'])],
|
|
66
68
|
['pnpm', new Set(['install'])],
|
|
@@ -113,6 +115,21 @@ export function detectWebTool(request) {
|
|
|
113
115
|
WEB_TOOL_KEYWORDS.some((keyword) => normalizedDesc.includes(keyword)));
|
|
114
116
|
});
|
|
115
117
|
}
|
|
118
|
+
/**
|
|
119
|
+
* Detect if a web_search tool is explicitly declared in the request tools list.
|
|
120
|
+
* This is used for routing decisions in the classifier.
|
|
121
|
+
*/
|
|
122
|
+
export function detectWebSearchToolDeclared(request) {
|
|
123
|
+
if (!Array.isArray(request.tools)) {
|
|
124
|
+
return false;
|
|
125
|
+
}
|
|
126
|
+
return request.tools.some((tool) => {
|
|
127
|
+
const functionName = extractToolName(tool);
|
|
128
|
+
const normalizedName = functionName.toLowerCase().replace(/[-_]/g, '');
|
|
129
|
+
// Match exact web_search tool name (with or without underscore/dash)
|
|
130
|
+
return normalizedName === 'websearch';
|
|
131
|
+
});
|
|
132
|
+
}
|
|
116
133
|
export function extractMeaningfulDeclaredToolNames(tools) {
|
|
117
134
|
if (!Array.isArray(tools) || tools.length === 0) {
|
|
118
135
|
return [];
|
|
@@ -547,9 +564,31 @@ function isSearchBinary(binary, args) {
|
|
|
547
564
|
if (SHELL_SEARCH_COMMANDS.has(normalized)) {
|
|
548
565
|
return true;
|
|
549
566
|
}
|
|
550
|
-
if (normalized === 'git'
|
|
551
|
-
|
|
552
|
-
|
|
567
|
+
if (normalized === 'git') {
|
|
568
|
+
if (containsSubcommand(args, GIT_SEARCH_SUBCOMMANDS)) {
|
|
569
|
+
return true;
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
if (normalized === 'bd') {
|
|
573
|
+
if (containsSubcommand(args, BD_SEARCH_SUBCOMMANDS)) {
|
|
574
|
+
return true;
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
return false;
|
|
578
|
+
}
|
|
579
|
+
function containsSubcommand(args, candidates) {
|
|
580
|
+
if (!Array.isArray(args) || args.length === 0 || !candidates.size) {
|
|
581
|
+
return false;
|
|
582
|
+
}
|
|
583
|
+
for (const raw of args) {
|
|
584
|
+
if (typeof raw !== 'string') {
|
|
585
|
+
continue;
|
|
586
|
+
}
|
|
587
|
+
const token = raw.trim().toLowerCase();
|
|
588
|
+
if (!token || token.startsWith('-')) {
|
|
589
|
+
continue;
|
|
590
|
+
}
|
|
591
|
+
if (candidates.has(token)) {
|
|
553
592
|
return true;
|
|
554
593
|
}
|
|
555
594
|
}
|
|
@@ -44,6 +44,10 @@ export interface ProviderAuthConfig {
|
|
|
44
44
|
oauthProviderId?: string;
|
|
45
45
|
rawType?: string;
|
|
46
46
|
}
|
|
47
|
+
export interface DeepSeekCompatRuntimeOptions {
|
|
48
|
+
strictToolRequired?: boolean;
|
|
49
|
+
textToolFallback?: boolean;
|
|
50
|
+
}
|
|
47
51
|
export interface ProviderProfile {
|
|
48
52
|
providerKey: string;
|
|
49
53
|
providerType: string;
|
|
@@ -57,6 +61,7 @@ export interface ProviderProfile {
|
|
|
57
61
|
responsesConfig?: ResponsesProviderConfig;
|
|
58
62
|
streaming?: StreamingPreference;
|
|
59
63
|
maxContextTokens?: number;
|
|
64
|
+
deepseek?: DeepSeekCompatRuntimeOptions;
|
|
60
65
|
/**
|
|
61
66
|
* When true, this provider must be skipped for any request that
|
|
62
67
|
* requires server-side tool orchestration (e.g. web_search).
|
|
@@ -83,6 +88,7 @@ export interface ProviderRuntimeProfile {
|
|
|
83
88
|
modelContextTokens?: Record<string, number>;
|
|
84
89
|
defaultContextTokens?: number;
|
|
85
90
|
maxContextTokens?: number;
|
|
91
|
+
deepseek?: DeepSeekCompatRuntimeOptions;
|
|
86
92
|
/**
|
|
87
93
|
* Provider-level flag propagated from virtualrouter.providers[*].
|
|
88
94
|
* When true, VirtualRouterEngine will skip this runtime for any
|
|
@@ -381,6 +387,7 @@ export interface RoutingFeatures {
|
|
|
381
387
|
hasVisionTool: boolean;
|
|
382
388
|
hasImageAttachment: boolean;
|
|
383
389
|
hasWebTool: boolean;
|
|
390
|
+
hasWebSearchToolDeclared?: boolean;
|
|
384
391
|
hasCodingTool: boolean;
|
|
385
392
|
hasThinkingKeyword: boolean;
|
|
386
393
|
estimatedTokens: number;
|
|
@@ -417,6 +424,7 @@ export interface TargetMetadata {
|
|
|
417
424
|
responsesConfig?: ResponsesProviderConfig;
|
|
418
425
|
streaming?: StreamingPreference;
|
|
419
426
|
maxContextTokens?: number;
|
|
427
|
+
deepseek?: DeepSeekCompatRuntimeOptions;
|
|
420
428
|
/**
|
|
421
429
|
* Route-level flags propagated from the virtual router.
|
|
422
430
|
* These are derived from routing pools and webSearch config and
|
|
@@ -449,7 +457,7 @@ export interface RoutingDiagnostics {
|
|
|
449
457
|
confidence: number;
|
|
450
458
|
}
|
|
451
459
|
export interface StopMessageStateSnapshot {
|
|
452
|
-
stopMessageText
|
|
460
|
+
stopMessageText?: string;
|
|
453
461
|
stopMessageMaxRepeats: number;
|
|
454
462
|
/**
|
|
455
463
|
* stopMessage 来源:
|
|
@@ -460,6 +468,16 @@ export interface StopMessageStateSnapshot {
|
|
|
460
468
|
stopMessageUsed?: number;
|
|
461
469
|
stopMessageUpdatedAt?: number;
|
|
462
470
|
stopMessageLastUsedAt?: number;
|
|
471
|
+
stopMessageStage?: string;
|
|
472
|
+
stopMessageStageMode?: 'on' | 'off' | 'auto';
|
|
473
|
+
stopMessageObservationHash?: string;
|
|
474
|
+
stopMessageObservationStableCount?: number;
|
|
475
|
+
stopMessageBdWorkState?: string;
|
|
476
|
+
}
|
|
477
|
+
export interface PreCommandStateSnapshot {
|
|
478
|
+
preCommandScriptPath: string;
|
|
479
|
+
preCommandSource?: string;
|
|
480
|
+
preCommandUpdatedAt?: number;
|
|
463
481
|
}
|
|
464
482
|
export interface RoutingStatusSnapshot {
|
|
465
483
|
routes: Record<string, {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { ClockConfigSnapshot } from './types.js';
|
|
2
2
|
export declare const CLOCK_CONFIG_DEFAULTS: {
|
|
3
3
|
readonly retentionMs: number;
|
|
4
|
-
readonly dueWindowMs:
|
|
4
|
+
readonly dueWindowMs: 0;
|
|
5
5
|
readonly tickMs: 60000;
|
|
6
6
|
readonly holdNonStreaming: true;
|
|
7
7
|
readonly holdMaxMs: 60000;
|
|
@@ -1,10 +1,35 @@
|
|
|
1
1
|
export const CLOCK_CONFIG_DEFAULTS = {
|
|
2
2
|
retentionMs: 20 * 60_000,
|
|
3
|
-
dueWindowMs:
|
|
3
|
+
dueWindowMs: 0,
|
|
4
4
|
tickMs: 60_000,
|
|
5
5
|
holdNonStreaming: true,
|
|
6
6
|
holdMaxMs: 60_000
|
|
7
7
|
};
|
|
8
|
+
function parseBooleanWithDefault(value, fallback) {
|
|
9
|
+
if (value === undefined) {
|
|
10
|
+
return fallback;
|
|
11
|
+
}
|
|
12
|
+
if (typeof value === 'boolean') {
|
|
13
|
+
return value;
|
|
14
|
+
}
|
|
15
|
+
if (typeof value === 'number') {
|
|
16
|
+
if (value === 1)
|
|
17
|
+
return true;
|
|
18
|
+
if (value === 0)
|
|
19
|
+
return false;
|
|
20
|
+
return fallback;
|
|
21
|
+
}
|
|
22
|
+
if (typeof value === 'string') {
|
|
23
|
+
const normalized = value.trim().toLowerCase();
|
|
24
|
+
if (normalized === 'true' || normalized === '1' || normalized === 'yes' || normalized === 'on') {
|
|
25
|
+
return true;
|
|
26
|
+
}
|
|
27
|
+
if (normalized === 'false' || normalized === '0' || normalized === 'no' || normalized === 'off') {
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return fallback;
|
|
32
|
+
}
|
|
8
33
|
export function normalizeClockConfig(raw) {
|
|
9
34
|
if (!raw || typeof raw !== 'object' || Array.isArray(raw)) {
|
|
10
35
|
return null;
|
|
@@ -25,9 +50,7 @@ export function normalizeClockConfig(raw) {
|
|
|
25
50
|
const tickMs = typeof record.tickMs === 'number' && Number.isFinite(record.tickMs) && record.tickMs >= 0
|
|
26
51
|
? Math.floor(record.tickMs)
|
|
27
52
|
: CLOCK_CONFIG_DEFAULTS.tickMs;
|
|
28
|
-
const holdNonStreaming = record.holdNonStreaming
|
|
29
|
-
(typeof record.holdNonStreaming === 'string' && record.holdNonStreaming.trim().toLowerCase() === 'true') ||
|
|
30
|
-
(typeof record.holdNonStreaming === 'number' && record.holdNonStreaming === 1);
|
|
53
|
+
const holdNonStreaming = parseBooleanWithDefault(record.holdNonStreaming, CLOCK_CONFIG_DEFAULTS.holdNonStreaming);
|
|
31
54
|
const holdMaxMs = typeof record.holdMaxMs === 'number' && Number.isFinite(record.holdMaxMs) && record.holdMaxMs >= 0
|
|
32
55
|
? Math.floor(record.holdMaxMs)
|
|
33
56
|
: CLOCK_CONFIG_DEFAULTS.holdMaxMs;
|
|
@@ -1,4 +1,29 @@
|
|
|
1
1
|
let clockOffsetMs = 0;
|
|
2
|
+
const CLOCK_OVERDUE_AUTO_REMOVE_MS = 60_000;
|
|
3
|
+
function normalizeRecurrence(raw) {
|
|
4
|
+
if (!raw || typeof raw !== 'object' || Array.isArray(raw)) {
|
|
5
|
+
return undefined;
|
|
6
|
+
}
|
|
7
|
+
const record = raw;
|
|
8
|
+
const rawKind = typeof record.kind === 'string' ? record.kind.trim().toLowerCase() : '';
|
|
9
|
+
const kind = rawKind === 'daily' || rawKind === 'weekly' || rawKind === 'interval'
|
|
10
|
+
? rawKind
|
|
11
|
+
: undefined;
|
|
12
|
+
const maxRunsRaw = Number(record.maxRuns);
|
|
13
|
+
const maxRuns = Number.isFinite(maxRunsRaw) ? Math.floor(maxRunsRaw) : NaN;
|
|
14
|
+
if (!kind || !Number.isFinite(maxRuns) || maxRuns <= 0) {
|
|
15
|
+
return undefined;
|
|
16
|
+
}
|
|
17
|
+
if (kind === 'interval') {
|
|
18
|
+
const minutesRaw = Number(record.everyMinutes);
|
|
19
|
+
const everyMinutes = Number.isFinite(minutesRaw) ? Math.floor(minutesRaw) : NaN;
|
|
20
|
+
if (!Number.isFinite(everyMinutes) || everyMinutes <= 0) {
|
|
21
|
+
return undefined;
|
|
22
|
+
}
|
|
23
|
+
return { kind, maxRuns, everyMinutes };
|
|
24
|
+
}
|
|
25
|
+
return { kind, maxRuns };
|
|
26
|
+
}
|
|
2
27
|
export function setClockOffsetMs(value) {
|
|
3
28
|
if (typeof value !== 'number' || !Number.isFinite(value))
|
|
4
29
|
return;
|
|
@@ -42,6 +67,7 @@ export function coerceState(raw, sessionId) {
|
|
|
42
67
|
? e.notBeforeRequestId.trim()
|
|
43
68
|
: undefined;
|
|
44
69
|
const deliveryCount = typeof e.deliveryCount === 'number' && Number.isFinite(e.deliveryCount) ? Math.max(0, Math.floor(e.deliveryCount)) : 0;
|
|
70
|
+
const recurrence = normalizeRecurrence(e.recurrence);
|
|
45
71
|
tasks.push({
|
|
46
72
|
taskId,
|
|
47
73
|
sessionId,
|
|
@@ -53,7 +79,8 @@ export function coerceState(raw, sessionId) {
|
|
|
53
79
|
...(args ? { arguments: args } : {}),
|
|
54
80
|
...(deliveredAtMs !== undefined ? { deliveredAtMs } : {}),
|
|
55
81
|
deliveryCount,
|
|
56
|
-
...(notBeforeRequestId ? { notBeforeRequestId } : {})
|
|
82
|
+
...(notBeforeRequestId ? { notBeforeRequestId } : {}),
|
|
83
|
+
...(recurrence ? { recurrence } : {})
|
|
57
84
|
});
|
|
58
85
|
}
|
|
59
86
|
const updatedAtMs = typeof record.updatedAtMs === 'number' && Number.isFinite(record.updatedAtMs) ? Math.floor(record.updatedAtMs) : nowMs();
|
|
@@ -66,7 +93,19 @@ export function cleanExpiredTasks(tasks, config, atMs) {
|
|
|
66
93
|
continue;
|
|
67
94
|
if (!Number.isFinite(task.dueAtMs))
|
|
68
95
|
continue;
|
|
69
|
-
|
|
96
|
+
const recurrence = normalizeRecurrence(task.recurrence);
|
|
97
|
+
const deliveryCount = typeof task.deliveryCount === 'number' && Number.isFinite(task.deliveryCount)
|
|
98
|
+
? Math.max(0, Math.floor(task.deliveryCount))
|
|
99
|
+
: 0;
|
|
100
|
+
if (recurrence) {
|
|
101
|
+
if (deliveryCount >= recurrence.maxRuns) {
|
|
102
|
+
continue;
|
|
103
|
+
}
|
|
104
|
+
out.push({ ...task, recurrence });
|
|
105
|
+
continue;
|
|
106
|
+
}
|
|
107
|
+
const oneShotRetentionMs = Math.max(0, Math.min(config.retentionMs, CLOCK_OVERDUE_AUTO_REMOVE_MS));
|
|
108
|
+
if (atMs > task.dueAtMs + oneShotRetentionMs) {
|
|
70
109
|
continue;
|
|
71
110
|
}
|
|
72
111
|
out.push(task);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export type { ClockConfigSnapshot, ClockReservation, ClockScheduleItem, ClockSessionState, ClockTask } from './types.js';
|
|
1
|
+
export type { ClockConfigSnapshot, ClockReservation, ClockScheduleItem, ClockSessionState, ClockTask, ClockTaskRecurrence, ClockTaskUpdatePatch } from './types.js';
|
|
2
2
|
export { normalizeClockConfig, resolveClockConfig } from './config.js';
|
|
3
3
|
export { startClockDaemonIfNeeded, stopClockDaemonForTests } from './daemon.js';
|
|
4
4
|
export { loadClockSessionState, clearClockSession } from './session-store.js';
|
|
5
|
-
export { cancelClockTask, clearClockTasks, commitClockReservation, findNextUndeliveredDueAtMs, listClockTasks, parseDueAtMs, reserveDueTasksForRequest, scheduleClockTasks, selectDueUndeliveredTasks } from './tasks.js';
|
|
5
|
+
export { cancelClockTask, clearClockTasks, commitClockReservation, findNextUndeliveredDueAtMs, listClockSessionIds, listClockTasks, parseDueAtMs, reserveDueTasksForRequest, scheduleClockTasks, selectDueUndeliveredTasks, updateClockTask } from './tasks.js';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export { normalizeClockConfig, resolveClockConfig } from './config.js';
|
|
2
2
|
export { startClockDaemonIfNeeded, stopClockDaemonForTests } from './daemon.js';
|
|
3
3
|
export { loadClockSessionState, clearClockSession } from './session-store.js';
|
|
4
|
-
export { cancelClockTask, clearClockTasks, commitClockReservation, findNextUndeliveredDueAtMs, listClockTasks, parseDueAtMs, reserveDueTasksForRequest, scheduleClockTasks, selectDueUndeliveredTasks } from './tasks.js';
|
|
4
|
+
export { cancelClockTask, clearClockTasks, commitClockReservation, findNextUndeliveredDueAtMs, listClockSessionIds, listClockTasks, parseDueAtMs, reserveDueTasksForRequest, scheduleClockTasks, selectDueUndeliveredTasks, updateClockTask } from './tasks.js';
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
import type { ClockConfigSnapshot, ClockReservation, ClockScheduleItem, ClockTask } from './types.js';
|
|
1
|
+
import type { ClockConfigSnapshot, ClockReservation, ClockScheduleItem, ClockTask, ClockTaskUpdatePatch } from './types.js';
|
|
2
2
|
export declare function parseDueAtMs(value: unknown): number | null;
|
|
3
|
+
export declare function listClockSessionIds(): Promise<string[]>;
|
|
3
4
|
export declare function listClockTasks(sessionId: string, config: ClockConfigSnapshot): Promise<ClockTask[]>;
|
|
4
5
|
export declare function scheduleClockTasks(sessionId: string, items: ClockScheduleItem[], config: ClockConfigSnapshot): Promise<ClockTask[]>;
|
|
6
|
+
export declare function updateClockTask(sessionId: string, taskId: string, patch: ClockTaskUpdatePatch, config: ClockConfigSnapshot): Promise<ClockTask | null>;
|
|
5
7
|
export declare function cancelClockTask(sessionId: string, taskId: string, config: ClockConfigSnapshot): Promise<boolean>;
|
|
6
8
|
export declare function clearClockTasks(sessionId: string, config: ClockConfigSnapshot): Promise<number>;
|
|
7
9
|
export declare function selectDueUndeliveredTasks(tasks: ClockTask[], config: ClockConfigSnapshot, atMs: number): ClockTask[];
|