mirror of
https://github.com/QwenLM/qwen-code.git
synced 2026-04-28 11:41:04 +00:00
Merge pull request #2280 from xuewenjie123/fix/hooks-json-schema-type
Some checks are pending
Qwen Code CI / Lint (push) Waiting to run
Qwen Code CI / Test (push) Blocked by required conditions
Qwen Code CI / Test-1 (push) Blocked by required conditions
Qwen Code CI / Test-2 (push) Blocked by required conditions
Qwen Code CI / Test-3 (push) Blocked by required conditions
Qwen Code CI / Test-4 (push) Blocked by required conditions
Qwen Code CI / Test-5 (push) Blocked by required conditions
Qwen Code CI / Test-6 (push) Blocked by required conditions
Qwen Code CI / Test-7 (push) Blocked by required conditions
Qwen Code CI / Test-8 (push) Blocked by required conditions
Qwen Code CI / Post Coverage Comment (push) Blocked by required conditions
Qwen Code CI / CodeQL (push) Waiting to run
E2E Tests / E2E Test (Linux) - sandbox:docker (push) Waiting to run
E2E Tests / E2E Test (Linux) - sandbox:none (push) Waiting to run
E2E Tests / E2E Test - macOS (push) Waiting to run
Some checks are pending
Qwen Code CI / Lint (push) Waiting to run
Qwen Code CI / Test (push) Blocked by required conditions
Qwen Code CI / Test-1 (push) Blocked by required conditions
Qwen Code CI / Test-2 (push) Blocked by required conditions
Qwen Code CI / Test-3 (push) Blocked by required conditions
Qwen Code CI / Test-4 (push) Blocked by required conditions
Qwen Code CI / Test-5 (push) Blocked by required conditions
Qwen Code CI / Test-6 (push) Blocked by required conditions
Qwen Code CI / Test-7 (push) Blocked by required conditions
Qwen Code CI / Test-8 (push) Blocked by required conditions
Qwen Code CI / Post Coverage Comment (push) Blocked by required conditions
Qwen Code CI / CodeQL (push) Waiting to run
E2E Tests / E2E Test (Linux) - sandbox:docker (push) Waiting to run
E2E Tests / E2E Test (Linux) - sandbox:none (push) Waiting to run
E2E Tests / E2E Test - macOS (push) Waiting to run
fix: correct hooks JSON schema type definition
This commit is contained in:
commit
110fcd7b7b
3 changed files with 263 additions and 3 deletions
|
|
@ -76,12 +76,98 @@ export interface SettingDefinition {
|
|||
mergeStrategy?: MergeStrategy;
|
||||
/** Enum type options */
|
||||
options?: readonly SettingEnumOption[];
|
||||
/** Schema for array items when type is 'array' */
|
||||
items?: SettingItemDefinition;
|
||||
}
|
||||
|
||||
/**
|
||||
* Schema definition for array item types.
|
||||
* Supports simple types (string, number, boolean) and complex object types.
|
||||
*/
|
||||
export interface SettingItemDefinition {
|
||||
type: 'string' | 'number' | 'boolean' | 'object' | 'array';
|
||||
properties?: Record<
|
||||
string,
|
||||
SettingItemDefinition & {
|
||||
required?: boolean;
|
||||
enum?: string[];
|
||||
additionalProperties?: SettingItemDefinition;
|
||||
}
|
||||
>;
|
||||
items?: SettingItemDefinition;
|
||||
required?: boolean;
|
||||
enum?: string[];
|
||||
description?: string;
|
||||
additionalProperties?: boolean | SettingItemDefinition;
|
||||
}
|
||||
|
||||
export interface SettingsSchema {
|
||||
[key: string]: SettingDefinition;
|
||||
}
|
||||
|
||||
/**
|
||||
* Common items schema for hook definitions.
|
||||
* Used by both UserPromptSubmit and Stop hooks.
|
||||
*/
|
||||
const HOOK_DEFINITION_ITEMS: SettingItemDefinition = {
|
||||
type: 'object',
|
||||
description:
|
||||
'A hook definition with an optional matcher and a list of hook configurations.',
|
||||
properties: {
|
||||
matcher: {
|
||||
type: 'string',
|
||||
description:
|
||||
'An optional matcher pattern to filter when this hook definition applies.',
|
||||
},
|
||||
sequential: {
|
||||
type: 'boolean',
|
||||
description:
|
||||
'Whether the hooks should be executed sequentially instead of in parallel.',
|
||||
},
|
||||
hooks: {
|
||||
type: 'array',
|
||||
description: 'The list of hook configurations to execute.',
|
||||
required: true,
|
||||
items: {
|
||||
type: 'object',
|
||||
description:
|
||||
'A hook configuration entry that defines a command to execute.',
|
||||
properties: {
|
||||
type: {
|
||||
type: 'string',
|
||||
description: 'The type of hook.',
|
||||
enum: ['command'],
|
||||
required: true,
|
||||
},
|
||||
command: {
|
||||
type: 'string',
|
||||
description: 'The command to execute when the hook is triggered.',
|
||||
required: true,
|
||||
},
|
||||
name: {
|
||||
type: 'string',
|
||||
description: 'An optional name for the hook.',
|
||||
},
|
||||
description: {
|
||||
type: 'string',
|
||||
description: 'An optional description of what the hook does.',
|
||||
},
|
||||
timeout: {
|
||||
type: 'number',
|
||||
description: 'Timeout in milliseconds for the hook execution.',
|
||||
},
|
||||
env: {
|
||||
type: 'object',
|
||||
description:
|
||||
'Environment variables to set when executing the hook command.',
|
||||
additionalProperties: { type: 'string' },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export type MemoryImportFormat = 'tree' | 'flat';
|
||||
export type DnsResolutionOrder = 'ipv4first' | 'verbatim';
|
||||
|
||||
|
|
@ -1233,6 +1319,7 @@ const SETTINGS_SCHEMA = {
|
|||
'Hooks that execute before agent processing. Can modify prompts or inject context.',
|
||||
showInDialog: false,
|
||||
mergeStrategy: MergeStrategy.CONCAT,
|
||||
items: HOOK_DEFINITION_ITEMS,
|
||||
},
|
||||
Stop: {
|
||||
type: 'array',
|
||||
|
|
@ -1244,6 +1331,7 @@ const SETTINGS_SCHEMA = {
|
|||
'Hooks that execute after agent processing. Can post-process responses or log interactions.',
|
||||
showInDialog: false,
|
||||
mergeStrategy: MergeStrategy.CONCAT,
|
||||
items: HOOK_DEFINITION_ITEMS,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
|
|||
|
|
@ -600,14 +600,130 @@
|
|||
"description": "Hooks that execute before agent processing. Can modify prompts or inject context.",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
"description": "A hook definition with an optional matcher and a list of hook configurations.",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"matcher": {
|
||||
"description": "An optional matcher pattern to filter when this hook definition applies.",
|
||||
"type": "string"
|
||||
},
|
||||
"sequential": {
|
||||
"description": "Whether the hooks should be executed sequentially instead of in parallel.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"hooks": {
|
||||
"description": "The list of hook configurations to execute.",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"description": "A hook configuration entry that defines a command to execute.",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": {
|
||||
"description": "The type of hook.",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"command"
|
||||
]
|
||||
},
|
||||
"command": {
|
||||
"description": "The command to execute when the hook is triggered.",
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"description": "An optional name for the hook.",
|
||||
"type": "string"
|
||||
},
|
||||
"description": {
|
||||
"description": "An optional description of what the hook does.",
|
||||
"type": "string"
|
||||
},
|
||||
"timeout": {
|
||||
"description": "Timeout in milliseconds for the hook execution.",
|
||||
"type": "number"
|
||||
},
|
||||
"env": {
|
||||
"description": "Environment variables to set when executing the hook command.",
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type",
|
||||
"command"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"hooks"
|
||||
]
|
||||
}
|
||||
},
|
||||
"Stop": {
|
||||
"description": "Hooks that execute after agent processing. Can post-process responses or log interactions.",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
"description": "A hook definition with an optional matcher and a list of hook configurations.",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"matcher": {
|
||||
"description": "An optional matcher pattern to filter when this hook definition applies.",
|
||||
"type": "string"
|
||||
},
|
||||
"sequential": {
|
||||
"description": "Whether the hooks should be executed sequentially instead of in parallel.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"hooks": {
|
||||
"description": "The list of hook configurations to execute.",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"description": "A hook configuration entry that defines a command to execute.",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": {
|
||||
"description": "The type of hook.",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"command"
|
||||
]
|
||||
},
|
||||
"command": {
|
||||
"description": "The command to execute when the hook is triggered.",
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"description": "An optional name for the hook.",
|
||||
"type": "string"
|
||||
},
|
||||
"description": {
|
||||
"description": "An optional description of what the hook does.",
|
||||
"type": "string"
|
||||
},
|
||||
"timeout": {
|
||||
"description": "Timeout in milliseconds for the hook execution.",
|
||||
"type": "number"
|
||||
},
|
||||
"env": {
|
||||
"description": "Environment variables to set when executing the hook command.",
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type",
|
||||
"command"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"hooks"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ import { fileURLToPath } from 'node:url';
|
|||
|
||||
import type {
|
||||
SettingDefinition,
|
||||
SettingItemDefinition,
|
||||
SettingsSchema,
|
||||
} from '../packages/cli/src/config/settingsSchema.js';
|
||||
import { getSettingsSchema } from '../packages/cli/src/config/settingsSchema.js';
|
||||
|
|
@ -37,6 +38,57 @@ interface JsonSchemaProperty {
|
|||
enum?: (string | number)[];
|
||||
default?: unknown;
|
||||
additionalProperties?: boolean | JsonSchemaProperty;
|
||||
required?: string[];
|
||||
}
|
||||
|
||||
function convertItemDefinitionToJsonSchema(
|
||||
itemDef: SettingItemDefinition,
|
||||
): JsonSchemaProperty {
|
||||
const schema: JsonSchemaProperty = {};
|
||||
|
||||
if (itemDef.description) {
|
||||
schema.description = itemDef.description;
|
||||
}
|
||||
|
||||
schema.type = itemDef.type;
|
||||
|
||||
if (itemDef.enum) {
|
||||
schema.enum = itemDef.enum;
|
||||
}
|
||||
|
||||
if (itemDef.type === 'object' && itemDef.properties) {
|
||||
schema.properties = {};
|
||||
const requiredFields: string[] = [];
|
||||
|
||||
for (const [key, childDef] of Object.entries(itemDef.properties)) {
|
||||
const childSchema = convertItemDefinitionToJsonSchema(childDef);
|
||||
schema.properties[key] = childSchema;
|
||||
if (childDef.required) {
|
||||
requiredFields.push(key);
|
||||
}
|
||||
}
|
||||
|
||||
if (requiredFields.length > 0) {
|
||||
schema.required = requiredFields;
|
||||
}
|
||||
}
|
||||
|
||||
if (itemDef.type === 'object' && itemDef.additionalProperties !== undefined) {
|
||||
if (typeof itemDef.additionalProperties === 'boolean') {
|
||||
schema.additionalProperties = itemDef.additionalProperties;
|
||||
} else {
|
||||
schema.additionalProperties = convertItemDefinitionToJsonSchema(
|
||||
itemDef.additionalProperties,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (itemDef.items) {
|
||||
schema.type = 'array';
|
||||
schema.items = convertItemDefinitionToJsonSchema(itemDef.items);
|
||||
}
|
||||
|
||||
return schema;
|
||||
}
|
||||
|
||||
function convertSettingToJsonSchema(
|
||||
|
|
@ -60,7 +112,11 @@ function convertSettingToJsonSchema(
|
|||
break;
|
||||
case 'array':
|
||||
schema.type = 'array';
|
||||
schema.items = { type: 'string' };
|
||||
if (setting.items) {
|
||||
schema.items = convertItemDefinitionToJsonSchema(setting.items);
|
||||
} else {
|
||||
schema.items = { type: 'string' };
|
||||
}
|
||||
break;
|
||||
case 'enum':
|
||||
if (setting.options && setting.options.length > 0) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue