@renseiai/agentfactory 0.8.17 → 0.8.19
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/src/governor/decision-engine-adapter.d.ts +43 -0
- package/dist/src/governor/decision-engine-adapter.d.ts.map +1 -0
- package/dist/src/governor/decision-engine-adapter.js +422 -0
- package/dist/src/governor/decision-engine-adapter.test.d.ts +2 -0
- package/dist/src/governor/decision-engine-adapter.test.d.ts.map +1 -0
- package/dist/src/governor/decision-engine-adapter.test.js +363 -0
- package/dist/src/governor/index.d.ts +1 -0
- package/dist/src/governor/index.d.ts.map +1 -1
- package/dist/src/governor/index.js +1 -0
- package/dist/src/manifest/route-manifest.d.ts.map +1 -1
- package/dist/src/manifest/route-manifest.js +4 -0
- package/dist/src/merge-queue/adapters/github-native.d.ts +8 -0
- package/dist/src/merge-queue/adapters/github-native.d.ts.map +1 -1
- package/dist/src/merge-queue/adapters/github-native.js +37 -7
- package/dist/src/merge-queue/adapters/github-native.test.js +71 -42
- package/dist/src/orchestrator/activity-emitter.d.ts +7 -0
- package/dist/src/orchestrator/activity-emitter.d.ts.map +1 -1
- package/dist/src/orchestrator/activity-emitter.js +19 -1
- package/dist/src/orchestrator/api-activity-emitter.d.ts +6 -0
- package/dist/src/orchestrator/api-activity-emitter.d.ts.map +1 -1
- package/dist/src/orchestrator/api-activity-emitter.js +35 -0
- package/dist/src/orchestrator/index.d.ts +2 -0
- package/dist/src/orchestrator/index.d.ts.map +1 -1
- package/dist/src/orchestrator/index.js +1 -0
- package/dist/src/orchestrator/issue-tracker-client.d.ts +2 -1
- package/dist/src/orchestrator/issue-tracker-client.d.ts.map +1 -1
- package/dist/src/orchestrator/orchestrator.d.ts +27 -0
- package/dist/src/orchestrator/orchestrator.d.ts.map +1 -1
- package/dist/src/orchestrator/orchestrator.js +331 -86
- package/dist/src/orchestrator/security-scan-event.d.ts +57 -0
- package/dist/src/orchestrator/security-scan-event.d.ts.map +1 -0
- package/dist/src/orchestrator/security-scan-event.js +192 -0
- package/dist/src/orchestrator/security-scan-event.test.d.ts +2 -0
- package/dist/src/orchestrator/security-scan-event.test.d.ts.map +1 -0
- package/dist/src/orchestrator/security-scan-event.test.js +219 -0
- package/dist/src/orchestrator/state-recovery.d.ts.map +1 -1
- package/dist/src/orchestrator/state-recovery.js +1 -0
- package/dist/src/orchestrator/work-types.d.ts +1 -1
- package/dist/src/orchestrator/work-types.d.ts.map +1 -1
- package/dist/src/providers/claude-provider.d.ts.map +1 -1
- package/dist/src/providers/claude-provider.js +11 -0
- package/dist/src/providers/codex-app-server-provider.d.ts +201 -0
- package/dist/src/providers/codex-app-server-provider.d.ts.map +1 -0
- package/dist/src/providers/codex-app-server-provider.js +786 -0
- package/dist/src/providers/codex-app-server-provider.test.d.ts +2 -0
- package/dist/src/providers/codex-app-server-provider.test.d.ts.map +1 -0
- package/dist/src/providers/codex-app-server-provider.test.js +529 -0
- package/dist/src/providers/codex-provider.d.ts +24 -4
- package/dist/src/providers/codex-provider.d.ts.map +1 -1
- package/dist/src/providers/codex-provider.js +58 -6
- package/dist/src/providers/index.d.ts +1 -0
- package/dist/src/providers/index.d.ts.map +1 -1
- package/dist/src/providers/index.js +1 -0
- package/dist/src/providers/types.d.ts +1 -0
- package/dist/src/providers/types.d.ts.map +1 -1
- package/dist/src/routing/observation-recorder.test.js +1 -1
- package/dist/src/routing/observation-store.d.ts +15 -1
- package/dist/src/routing/observation-store.d.ts.map +1 -1
- package/dist/src/routing/observation-store.test.js +17 -11
- package/dist/src/templates/index.d.ts +2 -1
- package/dist/src/templates/index.d.ts.map +1 -1
- package/dist/src/templates/index.js +1 -0
- package/dist/src/templates/registry.d.ts +23 -0
- package/dist/src/templates/registry.d.ts.map +1 -1
- package/dist/src/templates/registry.js +80 -0
- package/dist/src/templates/registry.test.js +3 -2
- package/dist/src/templates/schema.d.ts +31 -0
- package/dist/src/templates/schema.d.ts.map +1 -0
- package/dist/src/templates/schema.js +139 -0
- package/dist/src/templates/schema.test.d.ts +2 -0
- package/dist/src/templates/schema.test.d.ts.map +1 -0
- package/dist/src/templates/schema.test.js +215 -0
- package/dist/src/templates/types.d.ts +2 -0
- package/dist/src/templates/types.d.ts.map +1 -1
- package/dist/src/templates/types.js +1 -0
- package/dist/src/tools/index.d.ts +2 -0
- package/dist/src/tools/index.d.ts.map +1 -1
- package/dist/src/tools/index.js +1 -0
- package/dist/src/tools/tool-category.d.ts +16 -0
- package/dist/src/tools/tool-category.d.ts.map +1 -0
- package/dist/src/tools/tool-category.js +58 -0
- package/package.json +2 -2
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Template JSON Schema Generation
|
|
3
|
+
*
|
|
4
|
+
* Generates JSON Schema 7 definitions from WorkflowTemplate objects.
|
|
5
|
+
* Schema is derived from TemplateContext fields referenced in the template's
|
|
6
|
+
* prompt via Handlebars expressions.
|
|
7
|
+
*
|
|
8
|
+
* @see SUP-1758
|
|
9
|
+
*/
|
|
10
|
+
// ---------------------------------------------------------------------------
|
|
11
|
+
// Known TemplateContext field definitions
|
|
12
|
+
// ---------------------------------------------------------------------------
|
|
13
|
+
/**
|
|
14
|
+
* Maps TemplateContext field names to their JSON Schema 7 definitions.
|
|
15
|
+
* This is the source of truth for schema generation.
|
|
16
|
+
*/
|
|
17
|
+
const CONTEXT_FIELD_SCHEMAS = {
|
|
18
|
+
identifier: { type: 'string', description: 'Issue identifier, e.g., "SUP-123"' },
|
|
19
|
+
mentionContext: { type: 'string', description: 'Optional user mention text providing additional context' },
|
|
20
|
+
startStatus: { type: 'string', description: 'Status to show when agent starts, e.g., "Started"' },
|
|
21
|
+
completeStatus: { type: 'string', description: 'Status to show when agent completes, e.g., "Finished"' },
|
|
22
|
+
parentContext: { type: 'string', description: 'Pre-built enriched prompt for parent issues with sub-issues' },
|
|
23
|
+
subIssueList: { type: 'string', description: 'Formatted list of sub-issues with statuses' },
|
|
24
|
+
cycleCount: { type: 'integer', description: 'Current escalation cycle count' },
|
|
25
|
+
strategy: { type: 'string', description: 'Current escalation strategy' },
|
|
26
|
+
failureSummary: { type: 'string', description: 'Accumulated failure summary across cycles' },
|
|
27
|
+
attemptNumber: { type: 'integer', description: 'Attempt number within current phase' },
|
|
28
|
+
previousFailureReasons: {
|
|
29
|
+
type: 'array',
|
|
30
|
+
items: { type: 'string' },
|
|
31
|
+
description: 'List of previous failure reasons',
|
|
32
|
+
},
|
|
33
|
+
totalCostUsd: { type: 'number', description: 'Total cost in USD across all attempts' },
|
|
34
|
+
blockerIdentifier: { type: 'string', description: 'Blocker issue identifier' },
|
|
35
|
+
team: { type: 'string', description: 'Team name' },
|
|
36
|
+
repository: { type: 'string', description: 'Git repository URL pattern' },
|
|
37
|
+
projectPath: { type: 'string', description: 'Root directory for this project within the repo' },
|
|
38
|
+
sharedPaths: {
|
|
39
|
+
type: 'array',
|
|
40
|
+
items: { type: 'string' },
|
|
41
|
+
description: 'Shared directories that any project agent may modify',
|
|
42
|
+
},
|
|
43
|
+
useToolPlugins: { type: 'boolean', description: 'When true, agents use in-process tools instead of CLI' },
|
|
44
|
+
linearCli: { type: 'string', description: 'Command to invoke the Linear CLI (default: "pnpm af-linear")' },
|
|
45
|
+
packageManager: { type: 'string', description: 'Package manager used by the project (default: "pnpm")' },
|
|
46
|
+
buildCommand: { type: 'string', description: 'Build command override' },
|
|
47
|
+
testCommand: { type: 'string', description: 'Test command override' },
|
|
48
|
+
validateCommand: { type: 'string', description: 'Validation command override' },
|
|
49
|
+
phaseOutputs: {
|
|
50
|
+
type: 'object',
|
|
51
|
+
additionalProperties: {
|
|
52
|
+
type: 'object',
|
|
53
|
+
additionalProperties: true,
|
|
54
|
+
},
|
|
55
|
+
description: 'Collected outputs from upstream phases',
|
|
56
|
+
},
|
|
57
|
+
agentBugBacklog: { type: 'string', description: 'Linear project name for agent-improvement issues' },
|
|
58
|
+
};
|
|
59
|
+
/** Fields that are always required in a template config */
|
|
60
|
+
const ALWAYS_REQUIRED = ['identifier'];
|
|
61
|
+
// ---------------------------------------------------------------------------
|
|
62
|
+
// Handlebars expression extraction
|
|
63
|
+
// ---------------------------------------------------------------------------
|
|
64
|
+
/**
|
|
65
|
+
* Extract Handlebars variable references from a template prompt.
|
|
66
|
+
* Matches {{ varName }}, {{ varName.property }}, and handles
|
|
67
|
+
* conditionals like {{#if varName}} and {{#unless varName}}.
|
|
68
|
+
*
|
|
69
|
+
* Returns the set of top-level variable names referenced.
|
|
70
|
+
*/
|
|
71
|
+
export function extractTemplateVariables(prompt) {
|
|
72
|
+
const vars = new Set();
|
|
73
|
+
// Match {{ expr }}, {{#if expr}}, {{#unless expr}}, {{> partial}}, etc.
|
|
74
|
+
const patterns = [
|
|
75
|
+
/\{\{\s*([a-zA-Z_][a-zA-Z0-9_.]*)\s*\}\}/g, // {{ varName }} or {{ var.prop }}
|
|
76
|
+
/\{\{#(?:if|unless)\s+([a-zA-Z_][a-zA-Z0-9_.]*)/g, // {{#if varName}}
|
|
77
|
+
/\{\{#(?:each)\s+([a-zA-Z_][a-zA-Z0-9_.]*)/g, // {{#each varName}}
|
|
78
|
+
/\{\{#(?:with)\s+([a-zA-Z_][a-zA-Z0-9_.]*)/g, // {{#with varName}}
|
|
79
|
+
/\{\{\s*(?:eq|neq)\s+([a-zA-Z_][a-zA-Z0-9_.]*)/g, // {{ eq varName "value" }}
|
|
80
|
+
/\((?:eq|neq)\s+([a-zA-Z_][a-zA-Z0-9_.]*)/g, // (eq varName "value") — subexpression
|
|
81
|
+
];
|
|
82
|
+
for (const pattern of patterns) {
|
|
83
|
+
let match;
|
|
84
|
+
while ((match = pattern.exec(prompt)) !== null) {
|
|
85
|
+
const varName = match[1];
|
|
86
|
+
// Extract the top-level variable name (before any dot)
|
|
87
|
+
const topLevel = varName.split('.')[0];
|
|
88
|
+
// Skip Handlebars built-ins and partials
|
|
89
|
+
if (topLevel !== 'this' && topLevel !== 'else') {
|
|
90
|
+
vars.add(topLevel);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
return vars;
|
|
95
|
+
}
|
|
96
|
+
// ---------------------------------------------------------------------------
|
|
97
|
+
// Schema generation
|
|
98
|
+
// ---------------------------------------------------------------------------
|
|
99
|
+
/**
|
|
100
|
+
* Generate a JSON Schema 7 definition for a WorkflowTemplate's parameters.
|
|
101
|
+
*
|
|
102
|
+
* By default, only includes fields that are referenced in the template's
|
|
103
|
+
* prompt. Set `includeAllFields: true` to include all known TemplateContext fields.
|
|
104
|
+
*/
|
|
105
|
+
export function generateTemplateSchema(template, options) {
|
|
106
|
+
const includeAll = options?.includeAllFields ?? false;
|
|
107
|
+
const properties = {};
|
|
108
|
+
const required = [];
|
|
109
|
+
if (includeAll) {
|
|
110
|
+
// Include all known fields
|
|
111
|
+
for (const [field, schemaDef] of Object.entries(CONTEXT_FIELD_SCHEMAS)) {
|
|
112
|
+
properties[field] = schemaDef;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
else {
|
|
116
|
+
// Only include fields referenced in the template prompt
|
|
117
|
+
const referencedVars = extractTemplateVariables(template.prompt);
|
|
118
|
+
for (const varName of referencedVars) {
|
|
119
|
+
if (varName in CONTEXT_FIELD_SCHEMAS) {
|
|
120
|
+
properties[varName] = CONTEXT_FIELD_SCHEMAS[varName];
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
// Always include 'identifier' as required
|
|
125
|
+
for (const field of ALWAYS_REQUIRED) {
|
|
126
|
+
if (field in properties && !required.includes(field)) {
|
|
127
|
+
required.push(field);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
return {
|
|
131
|
+
$schema: 'http://json-schema.org/draft-07/schema#',
|
|
132
|
+
type: 'object',
|
|
133
|
+
title: `${template.metadata.name} config`,
|
|
134
|
+
description: template.metadata.description ?? `Configuration schema for ${template.metadata.name} template`,
|
|
135
|
+
properties,
|
|
136
|
+
required: required.length > 0 ? required : undefined,
|
|
137
|
+
additionalProperties: true,
|
|
138
|
+
};
|
|
139
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.test.d.ts","sourceRoot":"","sources":["../../../src/templates/schema.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { generateTemplateSchema, extractTemplateVariables } from './schema.js';
|
|
3
|
+
import { TemplateRegistry } from './registry.js';
|
|
4
|
+
// ---------------------------------------------------------------------------
|
|
5
|
+
// Helpers
|
|
6
|
+
// ---------------------------------------------------------------------------
|
|
7
|
+
function makeTemplate(prompt, overrides = {}) {
|
|
8
|
+
return {
|
|
9
|
+
apiVersion: 'v1',
|
|
10
|
+
kind: 'WorkflowTemplate',
|
|
11
|
+
metadata: {
|
|
12
|
+
name: 'test-template',
|
|
13
|
+
description: 'A test template',
|
|
14
|
+
workType: 'development',
|
|
15
|
+
},
|
|
16
|
+
prompt,
|
|
17
|
+
...overrides,
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
// ---------------------------------------------------------------------------
|
|
21
|
+
// extractTemplateVariables
|
|
22
|
+
// ---------------------------------------------------------------------------
|
|
23
|
+
describe('extractTemplateVariables', () => {
|
|
24
|
+
it('extracts simple variable references', () => {
|
|
25
|
+
const vars = extractTemplateVariables('Hello {{ identifier }}, your status is {{ startStatus }}');
|
|
26
|
+
expect(vars).toContain('identifier');
|
|
27
|
+
expect(vars).toContain('startStatus');
|
|
28
|
+
});
|
|
29
|
+
it('extracts dotted variable references (top-level only)', () => {
|
|
30
|
+
const vars = extractTemplateVariables('{{ phaseOutputs.dev.prUrl }}');
|
|
31
|
+
expect(vars).toContain('phaseOutputs');
|
|
32
|
+
expect(vars).not.toContain('dev');
|
|
33
|
+
});
|
|
34
|
+
it('extracts variables from #if blocks', () => {
|
|
35
|
+
const vars = extractTemplateVariables('{{#if parentContext}}Parent: {{ parentContext }}{{/if}}');
|
|
36
|
+
expect(vars).toContain('parentContext');
|
|
37
|
+
});
|
|
38
|
+
it('extracts variables from #unless blocks', () => {
|
|
39
|
+
const vars = extractTemplateVariables('{{#unless useToolPlugins}}Use CLI{{/unless}}');
|
|
40
|
+
expect(vars).toContain('useToolPlugins');
|
|
41
|
+
});
|
|
42
|
+
it('extracts variables from #each blocks', () => {
|
|
43
|
+
const vars = extractTemplateVariables('{{#each previousFailureReasons}}Reason: {{this}}{{/each}}');
|
|
44
|
+
expect(vars).toContain('previousFailureReasons');
|
|
45
|
+
// 'this' should be excluded
|
|
46
|
+
expect(vars).not.toContain('this');
|
|
47
|
+
});
|
|
48
|
+
it('extracts variables from eq/neq helpers', () => {
|
|
49
|
+
const vars = extractTemplateVariables('{{#if (eq strategy "decompose")}}Decompose{{/if}}');
|
|
50
|
+
expect(vars).toContain('strategy');
|
|
51
|
+
});
|
|
52
|
+
it('returns empty set for prompt with no variables', () => {
|
|
53
|
+
const vars = extractTemplateVariables('Plain text with no expressions');
|
|
54
|
+
expect(vars.size).toBe(0);
|
|
55
|
+
});
|
|
56
|
+
it('handles whitespace in expressions', () => {
|
|
57
|
+
const vars = extractTemplateVariables('{{ identifier }}');
|
|
58
|
+
expect(vars).toContain('identifier');
|
|
59
|
+
});
|
|
60
|
+
});
|
|
61
|
+
// ---------------------------------------------------------------------------
|
|
62
|
+
// generateTemplateSchema
|
|
63
|
+
// ---------------------------------------------------------------------------
|
|
64
|
+
describe('generateTemplateSchema', () => {
|
|
65
|
+
it('generates valid JSON Schema 7', () => {
|
|
66
|
+
const template = makeTemplate('{{ identifier }} - {{ strategy }}');
|
|
67
|
+
const schema = generateTemplateSchema(template);
|
|
68
|
+
expect(schema.$schema).toBe('http://json-schema.org/draft-07/schema#');
|
|
69
|
+
expect(schema.type).toBe('object');
|
|
70
|
+
});
|
|
71
|
+
it('includes only referenced fields by default', () => {
|
|
72
|
+
const template = makeTemplate('Issue {{ identifier }} with strategy {{ strategy }}');
|
|
73
|
+
const schema = generateTemplateSchema(template);
|
|
74
|
+
expect(schema.properties).toHaveProperty('identifier');
|
|
75
|
+
expect(schema.properties).toHaveProperty('strategy');
|
|
76
|
+
expect(schema.properties).not.toHaveProperty('buildCommand');
|
|
77
|
+
expect(schema.properties).not.toHaveProperty('testCommand');
|
|
78
|
+
});
|
|
79
|
+
it('includes all fields when includeAllFields is true', () => {
|
|
80
|
+
const template = makeTemplate('{{ identifier }}');
|
|
81
|
+
const schema = generateTemplateSchema(template, { includeAllFields: true });
|
|
82
|
+
expect(schema.properties).toHaveProperty('identifier');
|
|
83
|
+
expect(schema.properties).toHaveProperty('strategy');
|
|
84
|
+
expect(schema.properties).toHaveProperty('buildCommand');
|
|
85
|
+
expect(schema.properties).toHaveProperty('testCommand');
|
|
86
|
+
});
|
|
87
|
+
it('marks identifier as required', () => {
|
|
88
|
+
const template = makeTemplate('{{ identifier }}');
|
|
89
|
+
const schema = generateTemplateSchema(template);
|
|
90
|
+
expect(schema.required).toContain('identifier');
|
|
91
|
+
});
|
|
92
|
+
it('uses template name and description in schema', () => {
|
|
93
|
+
const template = makeTemplate('{{ identifier }}', {
|
|
94
|
+
metadata: {
|
|
95
|
+
name: 'my-template',
|
|
96
|
+
description: 'My custom template',
|
|
97
|
+
workType: 'development',
|
|
98
|
+
},
|
|
99
|
+
});
|
|
100
|
+
const schema = generateTemplateSchema(template);
|
|
101
|
+
expect(schema.title).toBe('my-template config');
|
|
102
|
+
expect(schema.description).toBe('My custom template');
|
|
103
|
+
});
|
|
104
|
+
it('sets additionalProperties to true (extensible)', () => {
|
|
105
|
+
const template = makeTemplate('{{ identifier }}');
|
|
106
|
+
const schema = generateTemplateSchema(template);
|
|
107
|
+
expect(schema.additionalProperties).toBe(true);
|
|
108
|
+
});
|
|
109
|
+
it('generates correct types for known fields', () => {
|
|
110
|
+
const template = makeTemplate('{{ identifier }} {{ cycleCount }} {{ useToolPlugins }} {{ previousFailureReasons }} {{ totalCostUsd }}');
|
|
111
|
+
const schema = generateTemplateSchema(template);
|
|
112
|
+
const props = schema.properties;
|
|
113
|
+
expect(props.identifier.type).toBe('string');
|
|
114
|
+
expect(props.cycleCount.type).toBe('integer');
|
|
115
|
+
expect(props.useToolPlugins.type).toBe('boolean');
|
|
116
|
+
expect(props.previousFailureReasons.type).toBe('array');
|
|
117
|
+
expect(props.totalCostUsd.type).toBe('number');
|
|
118
|
+
});
|
|
119
|
+
});
|
|
120
|
+
// ---------------------------------------------------------------------------
|
|
121
|
+
// TemplateRegistry.getSchema()
|
|
122
|
+
// ---------------------------------------------------------------------------
|
|
123
|
+
describe('TemplateRegistry.getSchema', () => {
|
|
124
|
+
it('returns null for unknown template', () => {
|
|
125
|
+
const registry = new TemplateRegistry();
|
|
126
|
+
expect(registry.getSchema('nonexistent')).toBeNull();
|
|
127
|
+
});
|
|
128
|
+
it('returns JSON Schema for registered template', () => {
|
|
129
|
+
const registry = new TemplateRegistry();
|
|
130
|
+
registry.initialize({
|
|
131
|
+
useBuiltinDefaults: false,
|
|
132
|
+
templates: {
|
|
133
|
+
development: makeTemplate('Work on {{ identifier }} using {{ buildCommand }}'),
|
|
134
|
+
},
|
|
135
|
+
});
|
|
136
|
+
const schema = registry.getSchema('development');
|
|
137
|
+
expect(schema).not.toBeNull();
|
|
138
|
+
expect(schema?.properties).toHaveProperty('identifier');
|
|
139
|
+
expect(schema?.properties).toHaveProperty('buildCommand');
|
|
140
|
+
});
|
|
141
|
+
it('passes options through to schema generator', () => {
|
|
142
|
+
const registry = new TemplateRegistry();
|
|
143
|
+
registry.initialize({
|
|
144
|
+
useBuiltinDefaults: false,
|
|
145
|
+
templates: {
|
|
146
|
+
development: makeTemplate('{{ identifier }}'),
|
|
147
|
+
},
|
|
148
|
+
});
|
|
149
|
+
const defaultSchema = registry.getSchema('development');
|
|
150
|
+
const fullSchema = registry.getSchema('development', { includeAllFields: true });
|
|
151
|
+
expect(Object.keys(defaultSchema.properties).length).toBeLessThan(Object.keys(fullSchema.properties).length);
|
|
152
|
+
});
|
|
153
|
+
});
|
|
154
|
+
// ---------------------------------------------------------------------------
|
|
155
|
+
// TemplateRegistry.validateConfig()
|
|
156
|
+
// ---------------------------------------------------------------------------
|
|
157
|
+
describe('TemplateRegistry.validateConfig', () => {
|
|
158
|
+
function createRegistryWithTemplate(prompt) {
|
|
159
|
+
const registry = new TemplateRegistry();
|
|
160
|
+
registry.initialize({
|
|
161
|
+
useBuiltinDefaults: false,
|
|
162
|
+
templates: {
|
|
163
|
+
development: makeTemplate(prompt),
|
|
164
|
+
},
|
|
165
|
+
});
|
|
166
|
+
return registry;
|
|
167
|
+
}
|
|
168
|
+
it('returns invalid for unknown template', () => {
|
|
169
|
+
const registry = new TemplateRegistry();
|
|
170
|
+
const result = registry.validateConfig('nonexistent', { identifier: 'SUP-1' });
|
|
171
|
+
expect(result.valid).toBe(false);
|
|
172
|
+
expect(result.errors[0]).toContain('not found');
|
|
173
|
+
});
|
|
174
|
+
it('validates required fields', () => {
|
|
175
|
+
const registry = createRegistryWithTemplate('{{ identifier }}');
|
|
176
|
+
const result = registry.validateConfig('development', {});
|
|
177
|
+
expect(result.valid).toBe(false);
|
|
178
|
+
expect(result.errors.some(e => e.includes('identifier'))).toBe(true);
|
|
179
|
+
});
|
|
180
|
+
it('accepts valid config', () => {
|
|
181
|
+
const registry = createRegistryWithTemplate('{{ identifier }} {{ strategy }}');
|
|
182
|
+
const result = registry.validateConfig('development', {
|
|
183
|
+
identifier: 'SUP-123',
|
|
184
|
+
strategy: 'normal',
|
|
185
|
+
});
|
|
186
|
+
expect(result.valid).toBe(true);
|
|
187
|
+
expect(result.errors).toHaveLength(0);
|
|
188
|
+
});
|
|
189
|
+
it('treats template expressions as valid for any field', () => {
|
|
190
|
+
const registry = createRegistryWithTemplate('{{ identifier }} {{ cycleCount }}');
|
|
191
|
+
const result = registry.validateConfig('development', {
|
|
192
|
+
identifier: '{{ issue.identifier }}',
|
|
193
|
+
cycleCount: '{{ escalation.cycleCount }}',
|
|
194
|
+
});
|
|
195
|
+
expect(result.valid).toBe(true);
|
|
196
|
+
});
|
|
197
|
+
it('detects type mismatches', () => {
|
|
198
|
+
const registry = createRegistryWithTemplate('{{ identifier }} {{ cycleCount }}');
|
|
199
|
+
const result = registry.validateConfig('development', {
|
|
200
|
+
identifier: 123, // should be string
|
|
201
|
+
cycleCount: 'not-a-number', // should be integer
|
|
202
|
+
});
|
|
203
|
+
expect(result.valid).toBe(false);
|
|
204
|
+
expect(result.errors.some(e => e.includes('identifier'))).toBe(true);
|
|
205
|
+
expect(result.errors.some(e => e.includes('cycleCount'))).toBe(true);
|
|
206
|
+
});
|
|
207
|
+
it('allows additional properties not in schema', () => {
|
|
208
|
+
const registry = createRegistryWithTemplate('{{ identifier }}');
|
|
209
|
+
const result = registry.validateConfig('development', {
|
|
210
|
+
identifier: 'SUP-123',
|
|
211
|
+
customField: 'custom-value',
|
|
212
|
+
});
|
|
213
|
+
expect(result.valid).toBe(true);
|
|
214
|
+
});
|
|
215
|
+
});
|
|
@@ -157,6 +157,7 @@ export declare const AgentWorkTypeSchema: z.ZodEnum<{
|
|
|
157
157
|
"qa-coordination": "qa-coordination";
|
|
158
158
|
"acceptance-coordination": "acceptance-coordination";
|
|
159
159
|
merge: "merge";
|
|
160
|
+
security: "security";
|
|
160
161
|
}>;
|
|
161
162
|
export declare const ToolPermissionSchema: z.ZodUnion<readonly [z.ZodObject<{
|
|
162
163
|
shell: z.ZodString;
|
|
@@ -181,6 +182,7 @@ export declare const WorkflowTemplateSchema: z.ZodObject<{
|
|
|
181
182
|
"qa-coordination": "qa-coordination";
|
|
182
183
|
"acceptance-coordination": "acceptance-coordination";
|
|
183
184
|
merge: "merge";
|
|
185
|
+
security: "security";
|
|
184
186
|
}>;
|
|
185
187
|
}, z.core.$strip>;
|
|
186
188
|
tools: z.ZodOptional<z.ZodObject<{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/templates/types.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/templates/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
export { ToolRegistry } from './registry.js';
|
|
2
2
|
export type { CreateServersResult } from './registry.js';
|
|
3
3
|
export type { ToolPlugin, ToolPluginContext } from './types.js';
|
|
4
|
+
export { classifyTool } from './tool-category.js';
|
|
5
|
+
export type { ToolCategory } from './tool-category.js';
|
|
4
6
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/tools/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAC5C,YAAY,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAA;AACxD,YAAY,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/tools/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAC5C,YAAY,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAA;AACxD,YAAY,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAA;AAC/D,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AACjD,YAAY,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA"}
|
package/dist/src/tools/index.js
CHANGED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool category classification based on tool name pattern matching.
|
|
3
|
+
*
|
|
4
|
+
* Classifies tools into functional categories for dashboard and analytics use.
|
|
5
|
+
*/
|
|
6
|
+
export type ToolCategory = 'security' | 'testing' | 'build' | 'deploy' | 'research' | 'general';
|
|
7
|
+
/**
|
|
8
|
+
* Classify a tool into a functional category based on its name.
|
|
9
|
+
*
|
|
10
|
+
* Handles both simple tool names (e.g. `Read`, `Bash`) and
|
|
11
|
+
* MCP-qualified names (e.g. `mcp__af-linear__af_linear_create_issue`).
|
|
12
|
+
*
|
|
13
|
+
* Returns `'general'` for tools that don't match any specific category.
|
|
14
|
+
*/
|
|
15
|
+
export declare function classifyTool(toolName: string): ToolCategory;
|
|
16
|
+
//# sourceMappingURL=tool-category.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool-category.d.ts","sourceRoot":"","sources":["../../../src/tools/tool-category.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,MAAM,MAAM,YAAY,GAAG,UAAU,GAAG,SAAS,GAAG,OAAO,GAAG,QAAQ,GAAG,UAAU,GAAG,SAAS,CAAA;AAwC/F;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,YAAY,CAU3D"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool category classification based on tool name pattern matching.
|
|
3
|
+
*
|
|
4
|
+
* Classifies tools into functional categories for dashboard and analytics use.
|
|
5
|
+
*/
|
|
6
|
+
const CATEGORY_PATTERNS = [
|
|
7
|
+
{
|
|
8
|
+
category: 'security',
|
|
9
|
+
patterns: /security|vuln|scan|sast|dast|sbom|cve|audit(?!.*\bno-audit\b)/i,
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
category: 'testing',
|
|
13
|
+
patterns: /test|jest|vitest|playwright|cypress|coverage|assert/i,
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
category: 'deploy',
|
|
17
|
+
patterns: /deploy|release|publish|docker|k8s|terraform|infra/i,
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
category: 'build',
|
|
21
|
+
patterns: /build|compile|bundle|webpack|vite|esbuild|tsc/i,
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
category: 'research',
|
|
25
|
+
patterns: /search|fetch|browse|read|grep|glob|explore/i,
|
|
26
|
+
},
|
|
27
|
+
];
|
|
28
|
+
/**
|
|
29
|
+
* Extract the tool-specific portion from an MCP-qualified tool name.
|
|
30
|
+
*
|
|
31
|
+
* MCP tool names follow the pattern `mcp__{pluginName}__{toolName}`.
|
|
32
|
+
* Returns the portion after the last `__` separator, or the original
|
|
33
|
+
* name if it's not MCP-qualified.
|
|
34
|
+
*/
|
|
35
|
+
function extractToolName(toolName) {
|
|
36
|
+
const lastSep = toolName.lastIndexOf('__');
|
|
37
|
+
if (lastSep !== -1 && lastSep < toolName.length - 2) {
|
|
38
|
+
return toolName.substring(lastSep + 2);
|
|
39
|
+
}
|
|
40
|
+
return toolName;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Classify a tool into a functional category based on its name.
|
|
44
|
+
*
|
|
45
|
+
* Handles both simple tool names (e.g. `Read`, `Bash`) and
|
|
46
|
+
* MCP-qualified names (e.g. `mcp__af-linear__af_linear_create_issue`).
|
|
47
|
+
*
|
|
48
|
+
* Returns `'general'` for tools that don't match any specific category.
|
|
49
|
+
*/
|
|
50
|
+
export function classifyTool(toolName) {
|
|
51
|
+
const name = extractToolName(toolName);
|
|
52
|
+
for (const { category, patterns } of CATEGORY_PATTERNS) {
|
|
53
|
+
if (patterns.test(name)) {
|
|
54
|
+
return category;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return 'general';
|
|
58
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@renseiai/agentfactory",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.19",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Multi-agent fleet management for coding agents — orchestrator, providers, crash recovery",
|
|
6
6
|
"author": "Rensei AI (https://rensei.ai)",
|
|
@@ -56,7 +56,7 @@
|
|
|
56
56
|
"@types/node": "^22.5.4",
|
|
57
57
|
"typescript": "^5.7.3",
|
|
58
58
|
"vitest": "^3.2.3",
|
|
59
|
-
"@renseiai/create-agentfactory-app": "0.8.
|
|
59
|
+
"@renseiai/create-agentfactory-app": "0.8.19"
|
|
60
60
|
},
|
|
61
61
|
"scripts": {
|
|
62
62
|
"build": "tsc",
|