@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.
Files changed (82) hide show
  1. package/dist/src/governor/decision-engine-adapter.d.ts +43 -0
  2. package/dist/src/governor/decision-engine-adapter.d.ts.map +1 -0
  3. package/dist/src/governor/decision-engine-adapter.js +422 -0
  4. package/dist/src/governor/decision-engine-adapter.test.d.ts +2 -0
  5. package/dist/src/governor/decision-engine-adapter.test.d.ts.map +1 -0
  6. package/dist/src/governor/decision-engine-adapter.test.js +363 -0
  7. package/dist/src/governor/index.d.ts +1 -0
  8. package/dist/src/governor/index.d.ts.map +1 -1
  9. package/dist/src/governor/index.js +1 -0
  10. package/dist/src/manifest/route-manifest.d.ts.map +1 -1
  11. package/dist/src/manifest/route-manifest.js +4 -0
  12. package/dist/src/merge-queue/adapters/github-native.d.ts +8 -0
  13. package/dist/src/merge-queue/adapters/github-native.d.ts.map +1 -1
  14. package/dist/src/merge-queue/adapters/github-native.js +37 -7
  15. package/dist/src/merge-queue/adapters/github-native.test.js +71 -42
  16. package/dist/src/orchestrator/activity-emitter.d.ts +7 -0
  17. package/dist/src/orchestrator/activity-emitter.d.ts.map +1 -1
  18. package/dist/src/orchestrator/activity-emitter.js +19 -1
  19. package/dist/src/orchestrator/api-activity-emitter.d.ts +6 -0
  20. package/dist/src/orchestrator/api-activity-emitter.d.ts.map +1 -1
  21. package/dist/src/orchestrator/api-activity-emitter.js +35 -0
  22. package/dist/src/orchestrator/index.d.ts +2 -0
  23. package/dist/src/orchestrator/index.d.ts.map +1 -1
  24. package/dist/src/orchestrator/index.js +1 -0
  25. package/dist/src/orchestrator/issue-tracker-client.d.ts +2 -1
  26. package/dist/src/orchestrator/issue-tracker-client.d.ts.map +1 -1
  27. package/dist/src/orchestrator/orchestrator.d.ts +27 -0
  28. package/dist/src/orchestrator/orchestrator.d.ts.map +1 -1
  29. package/dist/src/orchestrator/orchestrator.js +331 -86
  30. package/dist/src/orchestrator/security-scan-event.d.ts +57 -0
  31. package/dist/src/orchestrator/security-scan-event.d.ts.map +1 -0
  32. package/dist/src/orchestrator/security-scan-event.js +192 -0
  33. package/dist/src/orchestrator/security-scan-event.test.d.ts +2 -0
  34. package/dist/src/orchestrator/security-scan-event.test.d.ts.map +1 -0
  35. package/dist/src/orchestrator/security-scan-event.test.js +219 -0
  36. package/dist/src/orchestrator/state-recovery.d.ts.map +1 -1
  37. package/dist/src/orchestrator/state-recovery.js +1 -0
  38. package/dist/src/orchestrator/work-types.d.ts +1 -1
  39. package/dist/src/orchestrator/work-types.d.ts.map +1 -1
  40. package/dist/src/providers/claude-provider.d.ts.map +1 -1
  41. package/dist/src/providers/claude-provider.js +11 -0
  42. package/dist/src/providers/codex-app-server-provider.d.ts +201 -0
  43. package/dist/src/providers/codex-app-server-provider.d.ts.map +1 -0
  44. package/dist/src/providers/codex-app-server-provider.js +786 -0
  45. package/dist/src/providers/codex-app-server-provider.test.d.ts +2 -0
  46. package/dist/src/providers/codex-app-server-provider.test.d.ts.map +1 -0
  47. package/dist/src/providers/codex-app-server-provider.test.js +529 -0
  48. package/dist/src/providers/codex-provider.d.ts +24 -4
  49. package/dist/src/providers/codex-provider.d.ts.map +1 -1
  50. package/dist/src/providers/codex-provider.js +58 -6
  51. package/dist/src/providers/index.d.ts +1 -0
  52. package/dist/src/providers/index.d.ts.map +1 -1
  53. package/dist/src/providers/index.js +1 -0
  54. package/dist/src/providers/types.d.ts +1 -0
  55. package/dist/src/providers/types.d.ts.map +1 -1
  56. package/dist/src/routing/observation-recorder.test.js +1 -1
  57. package/dist/src/routing/observation-store.d.ts +15 -1
  58. package/dist/src/routing/observation-store.d.ts.map +1 -1
  59. package/dist/src/routing/observation-store.test.js +17 -11
  60. package/dist/src/templates/index.d.ts +2 -1
  61. package/dist/src/templates/index.d.ts.map +1 -1
  62. package/dist/src/templates/index.js +1 -0
  63. package/dist/src/templates/registry.d.ts +23 -0
  64. package/dist/src/templates/registry.d.ts.map +1 -1
  65. package/dist/src/templates/registry.js +80 -0
  66. package/dist/src/templates/registry.test.js +3 -2
  67. package/dist/src/templates/schema.d.ts +31 -0
  68. package/dist/src/templates/schema.d.ts.map +1 -0
  69. package/dist/src/templates/schema.js +139 -0
  70. package/dist/src/templates/schema.test.d.ts +2 -0
  71. package/dist/src/templates/schema.test.d.ts.map +1 -0
  72. package/dist/src/templates/schema.test.js +215 -0
  73. package/dist/src/templates/types.d.ts +2 -0
  74. package/dist/src/templates/types.d.ts.map +1 -1
  75. package/dist/src/templates/types.js +1 -0
  76. package/dist/src/tools/index.d.ts +2 -0
  77. package/dist/src/tools/index.d.ts.map +1 -1
  78. package/dist/src/tools/index.js +1 -0
  79. package/dist/src/tools/tool-category.d.ts +16 -0
  80. package/dist/src/tools/tool-category.d.ts.map +1 -0
  81. package/dist/src/tools/tool-category.js +58 -0
  82. 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,2 @@
1
+ export {};
2
+ //# sourceMappingURL=schema.test.d.ts.map
@@ -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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"}
@@ -31,6 +31,7 @@ const WORK_TYPES = [
31
31
  'qa-coordination',
32
32
  'acceptance-coordination',
33
33
  'merge',
34
+ 'security',
34
35
  ];
35
36
  export const AgentWorkTypeSchema = z.enum(WORK_TYPES);
36
37
  export const ToolPermissionSchema = z.union([
@@ -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"}
@@ -1 +1,2 @@
1
1
  export { ToolRegistry } from './registry.js';
2
+ export { classifyTool } from './tool-category.js';
@@ -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.17",
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.17"
59
+ "@renseiai/create-agentfactory-app": "0.8.19"
60
60
  },
61
61
  "scripts": {
62
62
  "build": "tsc",