@jsonstudio/llms 0.6.795 → 0.6.938

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 (184) hide show
  1. package/dist/bridge/routecodex-adapter.d.ts +74 -0
  2. package/dist/config-unified/enhanced-path-resolver.d.ts +5 -0
  3. package/dist/config-unified/unified-config.d.ts +26 -0
  4. package/dist/conversion/codec-registry.d.ts +10 -0
  5. package/dist/conversion/codecs/gemini-openai-codec.d.ts +16 -0
  6. package/dist/conversion/codecs/openai-openai-codec.d.ts +12 -0
  7. package/dist/conversion/codecs/responses-openai-codec.d.ts +12 -0
  8. package/dist/conversion/compat/profiles/chat-gemini.json +12 -0
  9. package/dist/conversion/config/config-manager.d.ts +212 -0
  10. package/dist/conversion/hub/config/types.d.ts +26 -0
  11. package/dist/conversion/hub/core/detour-registry.d.ts +9 -0
  12. package/dist/conversion/hub/core/hub-context.d.ts +21 -0
  13. package/dist/conversion/hub/core/index.d.ts +3 -0
  14. package/dist/conversion/hub/core/stage-driver.d.ts +30 -0
  15. package/dist/conversion/hub/format-adapters/anthropic-format-adapter.d.ts +16 -0
  16. package/dist/conversion/hub/format-adapters/chat-format-adapter.d.ts +17 -0
  17. package/dist/conversion/hub/format-adapters/gemini-format-adapter.d.ts +16 -0
  18. package/dist/conversion/hub/format-adapters/index.d.ts +21 -0
  19. package/dist/conversion/hub/hub-feature.d.ts +1 -0
  20. package/dist/conversion/hub/node-support.d.ts +19 -0
  21. package/dist/conversion/hub/pipeline/compat/compat-pipeline-executor.js +11 -0
  22. package/dist/conversion/hub/pipeline/compat/compat-types.d.ts +3 -0
  23. package/dist/conversion/hub/pipeline/hub-pipeline.d.ts +7 -0
  24. package/dist/conversion/hub/pipeline/hub-pipeline.js +71 -14
  25. package/dist/conversion/hub/pipeline/stages/req_process/req_process_stage1_tool_governance/index.js +4 -0
  26. package/dist/conversion/hub/pipeline/stages/resp_outbound/resp_outbound_stage1_client_remap/index.js +23 -1
  27. package/dist/conversion/hub/pipelines/inbound.d.ts +22 -0
  28. package/dist/conversion/hub/pipelines/outbound.d.ts +22 -0
  29. package/dist/conversion/hub/policy/policy-engine.d.ts +46 -0
  30. package/dist/conversion/hub/policy/policy-engine.js +176 -0
  31. package/dist/conversion/hub/policy/protocol-spec.d.ts +50 -0
  32. package/dist/conversion/hub/policy/protocol-spec.js +105 -0
  33. package/dist/conversion/hub/process/chat-process.d.ts +32 -0
  34. package/dist/conversion/hub/registry.d.ts +28 -0
  35. package/dist/conversion/hub/response/chat-response-utils.d.ts +6 -0
  36. package/dist/conversion/hub/response/provider-response.js +31 -0
  37. package/dist/conversion/hub/semantic-mappers/gemini-mapper.d.ts +7 -0
  38. package/dist/conversion/hub/semantic-mappers/gemini-mapper.js +87 -1
  39. package/dist/conversion/hub/semantic-mappers/index.d.ts +4 -0
  40. package/dist/conversion/hub/semantic-mappers/responses-mapper.d.ts +21 -0
  41. package/dist/conversion/hub/standardized-bridge.d.ts +12 -0
  42. package/dist/conversion/hub/types/chat-schema.d.ts +112 -0
  43. package/dist/conversion/hub/types/errors.d.ts +5 -0
  44. package/dist/conversion/hub/types/format-envelope.d.ts +7 -0
  45. package/dist/conversion/hub/types/index.d.ts +6 -0
  46. package/dist/conversion/hub/types/json.d.ts +9 -0
  47. package/dist/conversion/hub/types/node.d.ts +31 -0
  48. package/dist/conversion/responses/responses-openai-bridge.js +263 -10
  49. package/dist/conversion/schema-validator.d.ts +7 -0
  50. package/dist/conversion/shared/args-mapping.d.ts +18 -0
  51. package/dist/conversion/shared/chat-request-filters.d.ts +9 -0
  52. package/dist/conversion/shared/errors.d.ts +1 -1
  53. package/dist/conversion/shared/gemini-tool-utils.js +61 -0
  54. package/dist/conversion/shared/jsonish.d.ts +3 -0
  55. package/dist/conversion/shared/mcp-injection.d.ts +2 -0
  56. package/dist/conversion/shared/media.d.ts +1 -0
  57. package/dist/conversion/shared/openai-message-normalize.d.ts +1 -0
  58. package/dist/conversion/shared/payload-budget.d.ts +13 -0
  59. package/dist/conversion/shared/reasoning-mapping.d.ts +5 -0
  60. package/dist/conversion/shared/responses-request-adapter.d.ts +1 -28
  61. package/dist/conversion/shared/responses-request-adapter.js +1 -430
  62. package/dist/conversion/shared/snapshot-hooks.js +112 -4
  63. package/dist/conversion/shared/tool-governor.js +8 -2
  64. package/dist/conversion/shared/tool-harvester.d.ts +31 -0
  65. package/dist/conversion/shared/tool-mapping.js +10 -29
  66. package/dist/conversion/types.d.ts +33 -0
  67. package/dist/filters/builtin/add-fields-filter.d.ts +8 -0
  68. package/dist/filters/builtin/blacklist-filter.d.ts +8 -0
  69. package/dist/filters/builtin/whitelist-filter.d.ts +8 -0
  70. package/dist/filters/engine.d.ts +16 -0
  71. package/dist/filters/special/request-tool-choice-policy.d.ts +11 -0
  72. package/dist/filters/special/response-finish-invariants.d.ts +11 -0
  73. package/dist/filters/special/response-openai-to-responses-bridge.d.ts +13 -0
  74. package/dist/filters/special/response-tool-arguments-blacklist.d.ts +12 -0
  75. package/dist/filters/special/response-tool-arguments-schema-converge.d.ts +13 -0
  76. package/dist/filters/special/response-tool-arguments-stringify.d.ts +9 -0
  77. package/dist/filters/special/response-tool-arguments-whitelist.d.ts +11 -0
  78. package/dist/filters/special/tool-filter-hooks.d.ts +19 -0
  79. package/dist/filters/special/tool-post-constraints.d.ts +31 -0
  80. package/dist/filters/types.d.ts +68 -0
  81. package/dist/filters/utils/fieldmap-loader.d.ts +2 -0
  82. package/dist/filters/utils/snapshot-writer.d.ts +10 -0
  83. package/dist/guidance/index.d.ts +3 -0
  84. package/dist/guidance/index.js +78 -83
  85. package/dist/http/sse-response.d.ts +22 -0
  86. package/dist/router/virtual-router/bootstrap.d.ts +6 -0
  87. package/dist/router/virtual-router/bootstrap.js +49 -5
  88. package/dist/router/virtual-router/classifier.d.ts +10 -0
  89. package/dist/router/virtual-router/engine-selection.js +147 -15
  90. package/dist/router/virtual-router/engine.js +177 -31
  91. package/dist/router/virtual-router/error-center.d.ts +10 -0
  92. package/dist/router/virtual-router/features.d.ts +3 -0
  93. package/dist/router/virtual-router/routing-instructions.d.ts +23 -1
  94. package/dist/router/virtual-router/routing-instructions.js +120 -30
  95. package/dist/router/virtual-router/types.d.ts +11 -0
  96. package/dist/servertool/engine.js +189 -16
  97. package/dist/servertool/handlers/apply-patch-guard.js +269 -0
  98. package/dist/servertool/handlers/exec-command-guard.js +558 -0
  99. package/dist/servertool/handlers/followup-message-trimmer.d.ts +16 -0
  100. package/dist/servertool/handlers/followup-message-trimmer.js +198 -0
  101. package/dist/servertool/handlers/followup-request-builder.d.ts +17 -0
  102. package/dist/servertool/handlers/followup-request-builder.js +122 -0
  103. package/dist/servertool/handlers/gemini-empty-reply-continue.js +252 -51
  104. package/dist/servertool/handlers/iflow-model-error-retry.js +12 -22
  105. package/dist/servertool/handlers/stop-message-auto.js +237 -75
  106. package/dist/servertool/handlers/vision.js +15 -27
  107. package/dist/servertool/handlers/web-search.js +17 -43
  108. package/dist/servertool/server-side-tools.d.ts +3 -0
  109. package/dist/servertool/server-side-tools.js +3 -0
  110. package/dist/sse/json-to-sse/anthropic-json-to-sse-converter.d.ts +2 -1
  111. package/dist/sse/json-to-sse/chat-json-to-sse-converter.d.ts +80 -0
  112. package/dist/sse/json-to-sse/event-generators/chat.d.ts +55 -0
  113. package/dist/sse/json-to-sse/event-generators/responses.d.ts +99 -0
  114. package/dist/sse/json-to-sse/gemini-json-to-sse-converter.d.ts +2 -1
  115. package/dist/sse/json-to-sse/responses-json-to-sse-converter.d.ts +80 -0
  116. package/dist/sse/json-to-sse/sequencers/anthropic-sequencer.d.ts +1 -1
  117. package/dist/sse/json-to-sse/sequencers/chat-sequencer.d.ts +2 -2
  118. package/dist/sse/json-to-sse/sequencers/gemini-sequencer.d.ts +1 -1
  119. package/dist/sse/json-to-sse/sequencers/responses-sequencer.d.ts +40 -0
  120. package/dist/sse/shared/chat-serializer.d.ts +4 -0
  121. package/dist/sse/shared/constants.d.ts +272 -0
  122. package/dist/sse/shared/serializers/anthropic-event-serializer.d.ts +1 -1
  123. package/dist/sse/shared/serializers/base-serializer.d.ts +158 -0
  124. package/dist/sse/shared/serializers/chat-event-serializer.d.ts +82 -0
  125. package/dist/sse/shared/serializers/gemini-event-serializer.d.ts +1 -1
  126. package/dist/sse/shared/serializers/index.d.ts +2 -1
  127. package/dist/sse/shared/serializers/responses-event-serializer.d.ts +123 -0
  128. package/dist/sse/shared/serializers/types.d.ts +51 -0
  129. package/dist/sse/shared/utils.d.ts +254 -0
  130. package/dist/sse/shared/writer.d.ts +2 -2
  131. package/dist/sse/sse-to-json/anthropic-sse-to-json-converter.d.ts +1 -1
  132. package/dist/sse/sse-to-json/builders/anthropic-response-builder.d.ts +1 -1
  133. package/dist/sse/sse-to-json/builders/response-builder.d.ts +1 -1
  134. package/dist/sse/sse-to-json/chat-sse-to-json-converter.d.ts +2 -1
  135. package/dist/sse/sse-to-json/gemini-sse-to-json-converter.d.ts +2 -1
  136. package/dist/sse/sse-to-json/parsers/sse-parser.d.ts +73 -0
  137. package/dist/sse/sse-to-json/responses-sse-to-json-converter.d.ts +1 -1
  138. package/dist/sse/types/chat-types.d.ts +1 -1
  139. package/dist/sse/types/responses-types.d.ts +1 -1
  140. package/dist/tools/apply-patch/execution-capturer.d.ts +13 -0
  141. package/dist/tools/apply-patch/execution-capturer.js +158 -0
  142. package/dist/tools/apply-patch/regression-capturer.d.ts +1 -0
  143. package/dist/tools/apply-patch/regression-capturer.js +5 -4
  144. package/dist/tools/apply-patch/structured.js +109 -13
  145. package/dist/tools/apply-patch/validator.js +261 -17
  146. package/dist/tools/tool-registry.d.ts +8 -0
  147. package/dist/tools/tool-registry.js +2 -1
  148. package/package.json +4 -4
  149. package/dist/conversion/compat/actions/apply-patch-format-fixer.js +0 -233
  150. package/dist/conversion/config/compat-profiles.json +0 -38
  151. package/dist/conversion/hub/response/server-side-tools.d.ts +0 -26
  152. package/dist/conversion/hub/response/server-side-tools.js +0 -383
  153. package/dist/conversion/shared/bridge-conversation-store.d.ts +0 -41
  154. package/dist/conversion/shared/bridge-conversation-store.js +0 -279
  155. package/dist/conversion/shared/bridge-request-adapter.d.ts +0 -28
  156. package/dist/conversion/shared/bridge-request-adapter.js +0 -430
  157. package/dist/conversion/shared/responses-id-utils.js +0 -42
  158. package/dist/conversion/shared/responses-instructions.js +0 -113
  159. package/dist/conversion/shared/responses-message-utils.d.ts +0 -15
  160. package/dist/conversion/shared/responses-message-utils.js +0 -206
  161. package/dist/conversion/shared/responses-metadata.js +0 -1
  162. package/dist/conversion/shared/responses-output-utils.d.ts +0 -7
  163. package/dist/conversion/shared/responses-output-utils.js +0 -108
  164. package/dist/conversion/shared/responses-types.d.ts +0 -33
  165. package/dist/conversion/shared/tool-normalizers.d.ts +0 -4
  166. package/dist/conversion/shared/tool-normalizers.js +0 -84
  167. package/dist/filters/special/request-streaming-to-nonstreaming.d.ts +0 -13
  168. package/dist/filters/special/request-streaming-to-nonstreaming.js +0 -39
  169. package/dist/filters/special/response-apply-patch-toon-decode.d.ts +0 -23
  170. package/dist/filters/special/response-apply-patch-toon-decode.js +0 -460
  171. package/dist/filters/special/response-tool-arguments-toon-decode.d.ts +0 -10
  172. package/dist/filters/special/response-tool-arguments-toon-decode.js +0 -154
  173. package/dist/servertool/flow-types.d.ts +0 -40
  174. package/dist/servertool/flow-types.js +0 -1
  175. package/dist/servertool/orchestration-types.d.ts +0 -33
  176. package/dist/servertool/orchestration-types.js +0 -1
  177. package/dist/servertool/vision-tool.d.ts +0 -2
  178. package/dist/servertool/vision-tool.js +0 -185
  179. package/dist/tools/patch-args-normalizer.d.ts +0 -15
  180. package/dist/tools/patch-args-normalizer.js +0 -472
  181. package/dist/utils/toon.d.ts +0 -4
  182. package/dist/utils/toon.js +0 -75
  183. /package/dist/{conversion/compat/actions/apply-patch-format-fixer.d.ts → servertool/handlers/apply-patch-guard.d.ts} +0 -0
  184. /package/dist/{conversion/shared/responses-types.js → servertool/handlers/exec-command-guard.d.ts} +0 -0
@@ -25,44 +25,25 @@ function asSchema(value) {
25
25
  }
26
26
  return undefined;
27
27
  }
28
+ function isTruthyEnv(value) {
29
+ const v = typeof value === 'string' ? value.trim().toLowerCase() : '';
30
+ return v === '1' || v === 'true' || v === 'yes' || v === 'on';
31
+ }
28
32
  export function ensureApplyPatchSchema(seed) {
29
33
  const schema = seed ? { ...seed } : {};
30
34
  schema.type = typeof schema.type === 'string' ? schema.type : 'object';
31
35
  const properties = isPlainObject(schema.properties) ? { ...schema.properties } : {};
32
- properties.file = { type: 'string', description: 'Optional default file path for all changes' };
33
- properties.instructions = { type: 'string', description: 'Optional summary of the edit' };
34
- properties.changes = {
35
- type: 'array',
36
- minItems: 1,
37
- items: {
38
- type: 'object',
39
- additionalProperties: false,
40
- required: ['kind'],
41
- properties: {
42
- file: { type: 'string', description: 'Relative path for this change' },
43
- kind: {
44
- type: 'string',
45
- description: 'insert_after | insert_before | replace | delete | create_file | delete_file'
46
- },
47
- anchor: { type: 'string', description: 'Context snippet for insert operations' },
48
- target: { type: 'string', description: 'Snippet to replace/delete' },
49
- lines: {
50
- description: 'New content for insert/replace/create operations',
51
- oneOf: [
52
- { type: 'string' },
53
- { type: 'array', items: { type: 'string' } }
54
- ]
55
- },
56
- use_anchor_indent: { type: 'boolean', description: 'Reuse indentation from the anchor snippet' }
57
- }
58
- }
36
+ properties.patch = {
37
+ type: 'string',
38
+ description: 'Patch text (*** Begin Patch / *** End Patch or GNU unified diff).'
59
39
  };
40
+ properties.input = { type: 'string', description: 'Alias of patch (patch text). Prefer patch.' };
60
41
  schema.properties = properties;
61
42
  const requiredList = Array.isArray(schema.required)
62
43
  ? schema.required.filter((entry) => typeof entry === 'string')
63
44
  : [];
64
- if (!requiredList.includes('changes')) {
65
- requiredList.push('changes');
45
+ if (!requiredList.includes('patch')) {
46
+ requiredList.push('patch');
66
47
  }
67
48
  schema.required = requiredList;
68
49
  if (typeof schema.additionalProperties !== 'boolean') {
@@ -0,0 +1,33 @@
1
+ export interface ConversionProfile {
2
+ id: string;
3
+ incomingProtocol: string;
4
+ outgoingProtocol: string;
5
+ codec: string;
6
+ inputSchema?: string;
7
+ canonicalRequestSchema?: string;
8
+ canonicalResponseSchema?: string;
9
+ clientResponseSchema?: string;
10
+ trace?: boolean;
11
+ }
12
+ export interface ConversionConfigFile {
13
+ profiles: Record<string, Omit<ConversionProfile, 'id'>>;
14
+ endpointBindings?: Record<string, string>;
15
+ }
16
+ export interface ConversionContext {
17
+ requestId?: string;
18
+ endpoint?: string;
19
+ entryEndpoint?: string;
20
+ targetProtocol?: string;
21
+ stream?: boolean;
22
+ metadata?: Record<string, unknown>;
23
+ }
24
+ export interface ConversionResult {
25
+ profile: ConversionProfile;
26
+ payload: any;
27
+ }
28
+ export interface ConversionCodec {
29
+ readonly id: string;
30
+ initialize(): Promise<void>;
31
+ convertRequest(payload: any, profile: ConversionProfile, context: ConversionContext): Promise<any>;
32
+ convertResponse(payload: any, profile: ConversionProfile, context: ConversionContext): Promise<any>;
33
+ }
@@ -0,0 +1,8 @@
1
+ import type { Filter, FilterContext, FilterResult, JsonObject } from '../types.js';
2
+ export declare class AddFieldsFilter implements Filter<JsonObject> {
3
+ readonly name = "add_fields";
4
+ readonly stage: any;
5
+ private readonly fields;
6
+ constructor(stage: FilterContext['stage'], fields: Record<string, unknown>);
7
+ apply(input: JsonObject): FilterResult<JsonObject>;
8
+ }
@@ -0,0 +1,8 @@
1
+ import type { Filter, FilterContext, FilterResult, JsonObject } from '../types.js';
2
+ export declare class BlacklistFilter implements Filter<JsonObject> {
3
+ readonly name = "blacklist";
4
+ readonly stage: any;
5
+ private readonly deny;
6
+ constructor(stage: FilterContext['stage'], deny: string[]);
7
+ apply(input: JsonObject): FilterResult<JsonObject>;
8
+ }
@@ -0,0 +1,8 @@
1
+ import type { Filter, FilterContext, FilterResult, JsonObject } from '../types.js';
2
+ export declare class WhitelistFilter implements Filter<JsonObject> {
3
+ readonly name = "whitelist";
4
+ readonly stage: any;
5
+ private readonly allow;
6
+ constructor(stage: FilterContext['stage'], allow: string[]);
7
+ apply(input: JsonObject): FilterResult<JsonObject>;
8
+ }
@@ -0,0 +1,16 @@
1
+ import type { Filter, FilterContext, FieldMapConfig, JsonObject } from './types.js';
2
+ export declare class FilterEngine {
3
+ private readonly filters;
4
+ private fieldMap?;
5
+ private readonly transforms;
6
+ registerFilter(filter: Filter): void;
7
+ setFieldMap(config: FieldMapConfig): void;
8
+ registerTransform(name: string, fn: (v: unknown) => unknown): void;
9
+ run(stage: FilterContext['stage'], payload: JsonObject, ctxBase: Omit<FilterContext, 'stage'>): Promise<JsonObject>;
10
+ private applyFieldMap;
11
+ private coerce;
12
+ private deepClone;
13
+ private mutateWildcardPath;
14
+ private getByPath;
15
+ private setByPath;
16
+ }
@@ -0,0 +1,11 @@
1
+ import type { Filter, FilterContext, FilterResult, JsonObject } from '../types.js';
2
+ /**
3
+ * Tool choice policy:
4
+ * - If tools exist and no tool_choice, set tool_choice='auto'
5
+ * - If no tools, remove tool_choice
6
+ */
7
+ export declare class RequestToolChoicePolicyFilter implements Filter<JsonObject> {
8
+ readonly name = "request_tool_choice_policy";
9
+ readonly stage: FilterContext['stage'];
10
+ apply(input: JsonObject): FilterResult<JsonObject>;
11
+ }
@@ -0,0 +1,11 @@
1
+ import type { Filter, FilterContext, FilterResult, JsonObject } from '../types.js';
2
+ /**
3
+ * Ensure finish_reason and content invariants on response side:
4
+ * - If tool_calls present, finish_reason defaults to 'tool_calls'
5
+ * - If tool_calls present, message.content=null (Chat path)
6
+ */
7
+ export declare class ResponseFinishInvariantsFilter implements Filter<JsonObject> {
8
+ readonly name = "response_finish_invariants";
9
+ readonly stage: FilterContext['stage'];
10
+ apply(input: JsonObject): FilterResult<JsonObject>;
11
+ }
@@ -0,0 +1,13 @@
1
+ import type { Filter, FilterContext, JsonObject, FilterResult } from '../types.js';
2
+ /**
3
+ * ResponseOpenAIToResponsesBridgeFilter
4
+ * - 将 OpenAI Chat 形状的响应桥接为 OpenAI Responses 形状
5
+ * - 与 Anthropic 并行:使用 filter 进行形状/协议转换(而非 endpoint 分支)
6
+ * - 阶段:response_post(在基础规范化之后执行)
7
+ */
8
+ export declare class ResponseOpenAIToResponsesBridgeFilter implements Filter<JsonObject> {
9
+ readonly name = "response_openai_to_responses_bridge";
10
+ readonly stage: FilterContext['stage'];
11
+ apply(input: JsonObject, ctx: FilterContext): Promise<FilterResult<JsonObject>>;
12
+ }
13
+ export default ResponseOpenAIToResponsesBridgeFilter;
@@ -0,0 +1,12 @@
1
+ import type { Filter, FilterContext, FilterResult, JsonObject } from '../types.js';
2
+ /**
3
+ * ResponseToolArgumentsBlacklistFilter
4
+ * - Remove keys listed in ROUTECODEX_TOOLARGS_BLACKLIST from tool_calls[].function.arguments (after decode).
5
+ * - Default: empty blacklist (no-op). Enables incremental hardening without risking valid params.
6
+ * Stage: response_pre
7
+ */
8
+ export declare class ResponseToolArgumentsBlacklistFilter implements Filter<JsonObject> {
9
+ readonly name = "response_tool_arguments_blacklist";
10
+ readonly stage: FilterContext['stage'];
11
+ apply(input: JsonObject): FilterResult<JsonObject>;
12
+ }
@@ -0,0 +1,13 @@
1
+ import type { Filter, FilterContext, FilterResult, JsonObject } from '../types.js';
2
+ /**
3
+ * ResponseToolArgumentsSchemaConvergeFilter
4
+ * - If tool schemas are available on context (context.toolSchemas[name] = JSONSchema),
5
+ * keep only keys defined in schema.properties for each tool call arguments.
6
+ * - Does not validate or coerce types; only converges keys to schema surface.
7
+ * - Stage: response_pre
8
+ */
9
+ export declare class ResponseToolArgumentsSchemaConvergeFilter implements Filter<JsonObject> {
10
+ readonly name = "response_tool_arguments_schema_converge";
11
+ readonly stage: FilterContext['stage'];
12
+ apply(input: JsonObject, context?: FilterContext): FilterResult<JsonObject>;
13
+ }
@@ -0,0 +1,9 @@
1
+ import type { Filter, FilterContext, FilterResult, JsonObject } from '../types.js';
2
+ /**
3
+ * Ensure choices[*].message.tool_calls[].function.arguments is a JSON string.
4
+ */
5
+ export declare class ResponseToolArgumentsStringifyFilter implements Filter<JsonObject> {
6
+ readonly name = "response_tool_arguments_stringify";
7
+ readonly stage: FilterContext['stage'];
8
+ apply(input: JsonObject): FilterResult<JsonObject>;
9
+ }
@@ -0,0 +1,11 @@
1
+ import type { Filter, FilterContext, FilterResult, JsonObject } from '../types.js';
2
+ /**
3
+ * Whitelist tool function arguments keys after decode to match schema (e.g., keep only 'command'/'workdir').
4
+ * Stage: response_pre. Runs after TOON decode and before stringify.
5
+ */
6
+ export declare class ResponseToolArgumentsWhitelistFilter implements Filter<JsonObject> {
7
+ readonly name = "response_tool_arguments_whitelist";
8
+ readonly stage: FilterContext['stage'];
9
+ private getWhitelist;
10
+ apply(input: JsonObject, context?: FilterContext): FilterResult<JsonObject>;
11
+ }
@@ -0,0 +1,19 @@
1
+ import type { Filter, FilterContext, FilterResult, JsonObject } from '../types.js';
2
+ interface ToolFilterConfigCategoryPolicy {
3
+ mode?: 'allow' | 'block' | 'require_content';
4
+ requireContentTypes?: string[];
5
+ }
6
+ interface ToolFilterConfig {
7
+ categories?: {
8
+ vision?: ToolFilterConfigCategoryPolicy;
9
+ mcp?: ToolFilterConfigCategoryPolicy;
10
+ };
11
+ }
12
+ export declare function setGlobalToolFilterConfig(cfg: ToolFilterConfig | undefined): void;
13
+ export declare function getGlobalToolFilterConfig(): ToolFilterConfig;
14
+ export declare class ToolFilterHookFilter implements Filter<JsonObject> {
15
+ readonly name = "tool_filter_hook";
16
+ readonly stage: FilterContext['stage'];
17
+ apply(input: JsonObject, ctx: FilterContext): FilterResult<JsonObject>;
18
+ }
19
+ export {};
@@ -0,0 +1,31 @@
1
+ import type { Filter, FilterContext, FilterResult, JsonObject } from '../types.js';
2
+ type ConstraintMatchCondition = 'missing' | 'empty' | 'missingOrEmpty';
3
+ interface ToolConstraintRule {
4
+ id: string;
5
+ direction: 'request' | 'response' | 'both';
6
+ providerProtocol?: string;
7
+ providerId?: string;
8
+ modelId?: string;
9
+ toolNamePattern?: string;
10
+ path: string;
11
+ when: ConstraintMatchCondition;
12
+ action: 'warn' | 'patch' | 'drop';
13
+ patchText?: string;
14
+ }
15
+ interface ToolGovernanceConstraintsConfig {
16
+ rules: ToolConstraintRule[];
17
+ }
18
+ /**
19
+ * Tool post-constraints filter(请求/响应阶段的最后一小步约束):
20
+ * - 默认只记录(warn),不修改 payload;
21
+ * - 修剪/修复行为完全由配置驱动(ToolGovernanceConstraintsConfig);
22
+ * - 当前仅实现缺失/空 description 的简单场景,后续可按配置扩展。
23
+ */
24
+ export declare class ToolPostConstraintsFilter implements Filter<JsonObject> {
25
+ readonly name = "tool_post_constraints";
26
+ readonly stage: FilterContext['stage'];
27
+ private readonly config;
28
+ constructor(stage: FilterContext['stage'], config?: ToolGovernanceConstraintsConfig);
29
+ apply(input: JsonObject, ctx: FilterContext): FilterResult<JsonObject>;
30
+ }
31
+ export {};
@@ -0,0 +1,68 @@
1
+ export type JsonObject = Record<string, unknown>;
2
+ export type FilterStage = 'request_pre' | 'request_map' | 'request_post' | 'request_finalize' | 'response_pre' | 'response_map' | 'response_post' | 'response_finalize';
3
+ export interface FilterContext {
4
+ requestId?: string;
5
+ model?: string;
6
+ endpoint?: string;
7
+ provider?: string;
8
+ profile?: string;
9
+ stage: FilterStage;
10
+ stream?: boolean;
11
+ toolFilterHints?: ToolFilterHints;
12
+ debug?: {
13
+ emit?: (event: string, data: unknown) => void;
14
+ };
15
+ }
16
+ export interface FilterResult<T = JsonObject> {
17
+ ok: boolean;
18
+ data: T;
19
+ warnings?: string[];
20
+ metrics?: Record<string, unknown>;
21
+ }
22
+ export interface Filter<T = JsonObject> {
23
+ readonly name: string;
24
+ readonly stage: FilterStage;
25
+ apply(input: T, ctx: FilterContext): Promise<FilterResult<T>> | FilterResult<T>;
26
+ }
27
+ export type ToolFilterAction = 'allow' | 'block' | 'rewrite';
28
+ export interface ToolFilterDecision {
29
+ name: string;
30
+ action: ToolFilterAction;
31
+ reason?: string;
32
+ category?: string;
33
+ }
34
+ export interface ToolFilterHints {
35
+ requestedDecisions?: ToolFilterDecision[];
36
+ categories?: {
37
+ vision?: boolean;
38
+ mcp?: boolean;
39
+ webSearch?: boolean;
40
+ codeExecution?: boolean;
41
+ fileSearch?: boolean;
42
+ dataAnalysis?: boolean;
43
+ };
44
+ categoryOverrides?: {
45
+ vision?: 'allow' | 'block' | 'require_content';
46
+ mcp?: 'allow' | 'block';
47
+ };
48
+ decided?: ToolFilterDecision[];
49
+ }
50
+ export interface FieldMapRule {
51
+ sourcePath: string;
52
+ targetPath: string;
53
+ type?: 'string' | 'number' | 'boolean' | 'object' | 'array';
54
+ transform?: string;
55
+ }
56
+ export interface FieldMapConfig {
57
+ request?: FieldMapRule[];
58
+ response?: FieldMapRule[];
59
+ }
60
+ export interface WhitelistConfig {
61
+ allow: string[];
62
+ }
63
+ export interface BlacklistConfig {
64
+ deny: string[];
65
+ }
66
+ export interface AddFieldsConfig {
67
+ fields: Record<string, unknown>;
68
+ }
@@ -0,0 +1,2 @@
1
+ import type { FieldMapConfig } from '../types.js';
2
+ export declare function loadFieldMapConfig(relativeJsonPath: string): Promise<FieldMapConfig | null>;
@@ -0,0 +1,10 @@
1
+ import type { FilterStage } from '../types.js';
2
+ export declare function writeFilterSnapshot(options: {
3
+ requestId?: string;
4
+ endpoint?: string;
5
+ profile?: string;
6
+ stage: FilterStage;
7
+ name?: string;
8
+ tag?: string;
9
+ data: unknown;
10
+ }): Promise<void>;
@@ -0,0 +1,3 @@
1
+ export declare function augmentOpenAITools(tools: unknown[]): unknown[];
2
+ export declare function augmentAnthropicTools(tools: unknown[]): unknown[];
3
+ export declare function buildSystemToolGuidance(): string;
@@ -19,6 +19,58 @@ function appendOnce(desc, guidance, marker) {
19
19
  return base;
20
20
  return base ? `${base}\n\n${guidance}` : guidance;
21
21
  }
22
+ function buildApplyPatchGuidanceText() {
23
+ const marker = '[Codex ApplyPatch Guidance]';
24
+ const text = [
25
+ marker,
26
+ 'Send ONLY patch text (do not describe tools in prose).',
27
+ '',
28
+ '✅ Supported patch text formats:',
29
+ ' A) Internal patch format: "*** Begin Patch" / "*** End Patch" + "*** Update/Add/Delete File"',
30
+ ' B) GNU unified diff: "diff --git", "---/+++", "@@" hunks, /dev/null for new files',
31
+ '',
32
+ '✅ Create vs update:',
33
+ ' - "*** Update File" MUST target an existing file (no implicit create).',
34
+ ' - To create a file, use "*** Add File:" (or GNU diff with --- /dev/null).',
35
+ '',
36
+ '✅ Common pitfalls:',
37
+ ' - In "*** Add File", EVERY content line must start with "+".',
38
+ ' - In "*** Update File" hunks, EVERY line must start with one of: " " (context), "-" (remove), "+" (add), or "@@" (hunk header).',
39
+ '',
40
+ '✅ Minimal examples (patch text):',
41
+ '',
42
+ '1) Create a new file',
43
+ '```patch',
44
+ '*** Begin Patch',
45
+ '*** Add File: path/to/new.txt',
46
+ '+Line 1',
47
+ '+Line 2',
48
+ '*** End Patch',
49
+ '```',
50
+ '',
51
+ '2) Replace one line in an existing file (keep surrounding context)',
52
+ '```patch',
53
+ '*** Begin Patch',
54
+ '*** Update File: path/to/existing.txt',
55
+ '@@',
56
+ ' Line 1',
57
+ '-Line 2',
58
+ '+Modified Line 2',
59
+ ' Line 3',
60
+ '*** End Patch',
61
+ '```',
62
+ '',
63
+ '3) Delete a file',
64
+ '```patch',
65
+ '*** Begin Patch',
66
+ '*** Delete File: path/to/obsolete.txt',
67
+ '*** End Patch',
68
+ '```',
69
+ '',
70
+ 'Paths must stay relative to the workspace root (no leading "/" or drive letters).'
71
+ ].join('\n');
72
+ return { marker, text };
73
+ }
22
74
  function augmentShell(fn) {
23
75
  const marker = '[Codex Shell Guidance]';
24
76
  const guidance = [
@@ -59,53 +111,20 @@ function augmentShell(fn) {
59
111
  fn.description = appendOnce(fn.description, guidance, marker);
60
112
  }
61
113
  function augmentApplyPatch(fn) {
62
- const marker = '[Codex ApplyPatch Guidance]';
63
- const guidance = [
64
- marker,
65
- 'Provide structured edits instead of raw diff text. Always send JSON arguments with a `changes` array.',
66
- 'Each change describes one operation, e.g. `{ "file": "src/foo.ts", "kind": "insert_after", "anchor": "const foo = 1;", "lines": ["const bar = 2;"] }`.',
67
- 'Supported kinds: insert_after, insert_before, replace, delete, create_file, delete_file.',
68
- 'Paths must stay relative to the workspace root (no leading "/" or drive letters).',
69
- 'Insert operations require `anchor` text; replace/delete require exact `target` snippets; `lines` omit "+/-" prefixes.',
70
- 'If you must emit raw patch text, use "*** Begin Patch" / "*** End Patch" with "*** Update/Add/Delete File" headers (no "diff --git").',
71
- 'Do not output "*** Create File:"; use "*** Add File:".'
72
- ].join('\n');
114
+ const { marker, text: guidance } = buildApplyPatchGuidanceText();
73
115
  const params = ensureObjectSchema(fn.parameters);
74
116
  const props = params.properties;
75
- props.file = { type: 'string', description: 'Optional default file path (relative) for changes' };
76
- props.instructions = { type: 'string', description: 'Optional human-readable summary' };
77
- props.changes = {
78
- type: 'array',
79
- minItems: 1,
80
- items: {
81
- type: 'object',
82
- additionalProperties: false,
83
- required: ['kind'],
84
- properties: {
85
- file: { type: 'string', description: 'Relative path for this change (overrides top-level file)' },
86
- kind: {
87
- type: 'string',
88
- description: 'insert_after | insert_before | replace | delete | create_file | delete_file'
89
- },
90
- anchor: { type: 'string', description: 'Required for insert_before / insert_after' },
91
- target: { type: 'string', description: 'Snippet to replace/delete' },
92
- lines: {
93
- description: 'New content for insert/replace/create operations',
94
- oneOf: [
95
- { type: 'string' },
96
- { type: 'array', items: { type: 'string' } }
97
- ]
98
- },
99
- use_anchor_indent: {
100
- type: 'boolean',
101
- description: 'Reapply the indentation of the anchor snippet to inserted lines'
102
- }
103
- }
104
- }
117
+ props.patch = {
118
+ type: 'string',
119
+ description: 'Patch text. Supports "*** Begin Patch" format or GNU unified diff. Paths must be workspace-relative.'
120
+ };
121
+ props.input = {
122
+ type: 'string',
123
+ description: 'Alias of patch (patch text). Prefer using patch.'
105
124
  };
106
125
  params.required = Array.isArray(params.required) ? params.required : [];
107
- if (!params.required.includes('changes')) {
108
- params.required.push('changes');
126
+ if (!params.required.includes('patch')) {
127
+ params.required.push('patch');
109
128
  }
110
129
  params.additionalProperties = false;
111
130
  fn.parameters = params;
@@ -161,8 +180,11 @@ export function augmentOpenAITools(tools) {
161
180
  try {
162
181
  if (n === 'shell')
163
182
  augmentShell(fn);
164
- else if (n === 'apply_patch')
183
+ else if (n === 'apply_patch') {
184
+ const { marker, text } = buildApplyPatchGuidanceText();
185
+ fn.description = appendOnce(fn.description, text, marker);
165
186
  augmentApplyPatch(fn);
187
+ }
166
188
  else if (n === 'update_plan')
167
189
  augmentUpdatePlan(fn);
168
190
  else if (n === 'view_image')
@@ -194,49 +216,22 @@ export function augmentAnthropicTools(tools) {
194
216
  const n = name.trim();
195
217
  try {
196
218
  if (n === 'apply_patch') {
197
- if (!isObject(schema.properties?.changes)) {
198
- schema.properties.file = { type: 'string', description: 'Optional default file path' };
199
- schema.properties.instructions = { type: 'string', description: 'Optional summary' };
200
- schema.properties.changes = {
201
- type: 'array',
202
- minItems: 1,
203
- items: {
204
- type: 'object',
205
- additionalProperties: false,
206
- required: ['kind'],
207
- properties: {
208
- file: { type: 'string' },
209
- kind: { type: 'string' },
210
- anchor: { type: 'string' },
211
- target: { type: 'string' },
212
- lines: {
213
- oneOf: [
214
- { type: 'string' },
215
- { type: 'array', items: { type: 'string' } }
216
- ]
217
- },
218
- use_anchor_indent: { type: 'boolean' }
219
- }
220
- }
221
- };
222
- }
219
+ schema.properties.patch = {
220
+ type: 'string',
221
+ description: 'Patch text (*** Begin Patch / *** End Patch or GNU unified diff).'
222
+ };
223
+ schema.properties.input = {
224
+ type: 'string',
225
+ description: 'Alias of patch (patch text). Prefer patch.'
226
+ };
223
227
  if (!Array.isArray(schema.required))
224
228
  schema.required = [];
225
- if (!schema.required.includes('changes'))
226
- schema.required.push('changes');
229
+ if (!schema.required.includes('patch'))
230
+ schema.required.push('patch');
227
231
  schema.additionalProperties = false;
228
232
  copy.input_schema = schema;
229
233
  const marker = '[Codex ApplyPatch Guidance]';
230
- const guidance = [
231
- marker,
232
- 'Before using apply_patch, always read the latest content of the target file (via shell or another tool) and base your changes on that content.',
233
- 'Provide structured changes (insert_after / insert_before / replace / delete / create_file / delete_file) instead of raw patch text.',
234
- 'Each change must include the target file (relative path) plus anchor/target snippets and the replacement lines.',
235
- '所有路径必须相对工作区根目录,禁止输出以 / 或盘符开头的绝对路径。',
236
- 'Example: {\"changes\":[{\"file\":\"src/app.ts\",\"kind\":\"replace\",\"target\":\"const answer = 41;\",\"lines\":[\"const answer = 42;\"]}]}(修改同一文件时尽量只修改一段连续区域,多处不相邻修改请拆成多次 apply_patch 调用).',
237
- 'Raw patch text must use "*** Begin Patch" / "*** End Patch" + "*** Update/Add/Delete File" headers(不要输出 "diff --git")。',
238
- '不要输出 "*** Create File:";请使用 "*** Add File:".'
239
- ].join('\n');
234
+ const guidance = buildApplyPatchGuidanceText().text;
240
235
  copy.description = appendOnce(desc, guidance, marker);
241
236
  }
242
237
  if (n === 'shell') {
@@ -271,7 +266,7 @@ export function buildSystemToolGuidance() {
271
266
  lines.push(bullet('shell: Place ALL intent into the command argv array only; do not invent extra keys. / shell 所有意图写入 command 数组,不要添加额外键名。'));
272
267
  lines.push(bullet('File writes are FORBIDDEN via shell (no redirection, no here-doc, no sed -i, no ed -s, no tee). Use apply_patch ONLY. / 通过 shell 写文件一律禁止(不得使用重定向、heredoc、sed -i、ed -s、tee);必须使用 apply_patch。'));
273
268
  lines.push(bullet('apply_patch: Before writing, always read the target file first and compute changes against the latest content using appropriate tools. / apply_patch 在写入前必须先通过合适的工具读取目标文件最新内容,并基于该内容生成变更。'));
274
- lines.push(bullet('apply_patch: Provide structured JSON arguments with a `changes` array (insert_after / insert_before / replace / delete / create_file / delete_file); omit "+/-" prefixes in `lines`; file paths必须是相对路径。 / apply_patch 仅接受结构化 JSON。'));
269
+ lines.push(bullet('apply_patch: Send patch text only. Supported formats: "*** Begin Patch" OR GNU unified diff. "*** Update File" never implicitly creates files—use "*** Add File:" (or /dev/null diff). / apply_patch:仅发送补丁文本,支持 "*** Begin Patch" 或 GNU diff;"*** Update File" 不会隐式创建文件。'));
275
270
  lines.push(bullet('apply_patch: For a given file, prefer one contiguous change block per call; if you need to touch non-adjacent regions, split them into multiple apply_patch calls. / apply_patch 修改同一文件时尽量只提交一段连续补丁,多个不相邻位置请拆成多次调用。'));
276
271
  lines.push(bullet('update_plan: Keep exactly one step in_progress; others pending/completed. / 仅一个 in_progress 步骤。'));
277
272
  lines.push(bullet('view_image: Path must be an image file (.png .jpg .jpeg .gif .webp .bmp .svg). / 仅图片路径。'));
@@ -0,0 +1,22 @@
1
+ import type { ServerResponse } from 'node:http';
2
+ import type { Readable } from 'node:stream';
3
+ type AnyObj = Record<string, unknown>;
4
+ /**
5
+ * Pipe an SSE Readable to Node http.ServerResponse
6
+ */
7
+ export declare function sendNodeSSE(res: ServerResponse, stream: Readable): void;
8
+ /**
9
+ * Express response variant (duck-typed): res.set, res.write, res.end
10
+ */
11
+ export declare function sendExpressSSE(res: AnyObj, stream: Readable): void;
12
+ /**
13
+ * Fastify reply variant: reply.raw is ServerResponse
14
+ */
15
+ export declare function sendFastifySSE(reply: AnyObj, stream: Readable): void;
16
+ /**
17
+ * If the given payload contains __sse_responses or sseStream, stream it via the provided response object.
18
+ * Otherwise, send JSON.
19
+ * - Supported responders: Node ServerResponse, Express res, Fastify reply
20
+ */
21
+ export declare function sendSSEOrJSON(resOrReply: AnyObj, payload: AnyObj): any;
22
+ export {};
@@ -0,0 +1,6 @@
1
+ import { type VirtualRouterBootstrapInput, type VirtualRouterBootstrapResult } from './types.js';
2
+ /**
3
+ * 将用户提供的 Virtual Router 配置(或包含 virtualrouter 字段的整体配置)
4
+ * 规范化为 VirtualRouterConfig,供 HubPipeline / VirtualRouterEngine 直接使用。
5
+ */
6
+ export declare function bootstrapVirtualRouterConfig(input: VirtualRouterBootstrapInput): VirtualRouterBootstrapResult;