agentxchain 2.2.0 → 2.3.0
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/README.md +16 -0
- package/bin/agentxchain.js +89 -0
- package/package.json +7 -2
- package/scripts/publish-from-tag.sh +14 -9
- package/scripts/release-postflight.sh +42 -2
- package/src/commands/intake-approve.js +44 -0
- package/src/commands/intake-plan.js +62 -0
- package/src/commands/intake-record.js +86 -0
- package/src/commands/intake-resolve.js +45 -0
- package/src/commands/intake-scan.js +87 -0
- package/src/commands/intake-start.js +53 -0
- package/src/commands/intake-status.js +113 -0
- package/src/commands/intake-triage.js +54 -0
- package/src/commands/verify.js +8 -3
- package/src/lib/adapters/api-proxy-adapter.js +125 -27
- package/src/lib/intake.js +924 -0
- package/src/lib/normalized-config.js +10 -0
- package/src/lib/protocol-conformance.js +28 -4
- package/src/lib/repo-observer.js +1 -0
|
@@ -13,9 +13,11 @@
|
|
|
13
13
|
*/
|
|
14
14
|
|
|
15
15
|
import { validateHooksConfig } from './hook-runner.js';
|
|
16
|
+
import { SUPPORTED_TOKEN_COUNTER_PROVIDERS } from './token-counter.js';
|
|
16
17
|
|
|
17
18
|
const VALID_WRITE_AUTHORITIES = ['authoritative', 'proposed', 'review_only'];
|
|
18
19
|
const VALID_RUNTIME_TYPES = ['manual', 'local_cli', 'api_proxy'];
|
|
20
|
+
const VALID_API_PROXY_PROVIDERS = ['anthropic', 'openai'];
|
|
19
21
|
const VALID_PROMPT_TRANSPORTS = ['argv', 'stdin', 'dispatch_bundle_only'];
|
|
20
22
|
const VALID_PHASES = ['planning', 'implementation', 'qa'];
|
|
21
23
|
const VALID_API_PROXY_RETRY_JITTER = ['none', 'full'];
|
|
@@ -146,6 +148,12 @@ function validateApiProxyPreflightTokenization(runtimeId, runtime, errors) {
|
|
|
146
148
|
}
|
|
147
149
|
|
|
148
150
|
if (preflight.enabled === true) {
|
|
151
|
+
if (!SUPPORTED_TOKEN_COUNTER_PROVIDERS.includes(runtime.provider)) {
|
|
152
|
+
errors.push(
|
|
153
|
+
`Runtime "${runtimeId}": preflight_tokenization tokenizer "provider_local" is not supported for provider "${runtime.provider}". Supported providers: ${SUPPORTED_TOKEN_COUNTER_PROVIDERS.join(', ')}`
|
|
154
|
+
);
|
|
155
|
+
}
|
|
156
|
+
|
|
149
157
|
if (!Number.isInteger(runtime.context_window_tokens) || runtime.context_window_tokens <= 0) {
|
|
150
158
|
errors.push(`Runtime "${runtimeId}": context_window_tokens is required when preflight_tokenization.enabled is true`);
|
|
151
159
|
return;
|
|
@@ -239,6 +247,8 @@ export function validateV4Config(data, projectRoot) {
|
|
|
239
247
|
if (rt.type === 'api_proxy') {
|
|
240
248
|
if (typeof rt.provider !== 'string' || !rt.provider.trim()) {
|
|
241
249
|
errors.push(`Runtime "${id}": api_proxy requires "provider" (e.g. "anthropic", "openai")`);
|
|
250
|
+
} else if (!VALID_API_PROXY_PROVIDERS.includes(rt.provider)) {
|
|
251
|
+
errors.push(`Runtime "${id}": api_proxy provider must be one of: ${VALID_API_PROXY_PROVIDERS.join(', ')}`);
|
|
242
252
|
}
|
|
243
253
|
if (typeof rt.model !== 'string' || !rt.model.trim()) {
|
|
244
254
|
errors.push(`Runtime "${id}": api_proxy requires "model" (e.g. "claude-sonnet-4-6")`);
|
|
@@ -5,7 +5,7 @@ import { fileURLToPath } from 'node:url';
|
|
|
5
5
|
|
|
6
6
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
7
7
|
const DEFAULT_FIXTURE_ROOT = resolve(__dirname, '..', '..', '..', '.agentxchain-conformance', 'fixtures');
|
|
8
|
-
const VALID_RESPONSE_STATUSES = new Set(['pass', 'fail', 'error']);
|
|
8
|
+
const VALID_RESPONSE_STATUSES = new Set(['pass', 'fail', 'error', 'not_implemented']);
|
|
9
9
|
const VALID_TIERS = new Set([1, 2, 3]);
|
|
10
10
|
|
|
11
11
|
function readJsonFile(filePath) {
|
|
@@ -119,16 +119,18 @@ function createTierSummary(status = 'skipped', note = null) {
|
|
|
119
119
|
fixtures_passed: 0,
|
|
120
120
|
fixtures_failed: 0,
|
|
121
121
|
fixtures_errored: 0,
|
|
122
|
+
fixtures_not_implemented: 0,
|
|
122
123
|
surfaces: {},
|
|
123
124
|
failures: [],
|
|
124
125
|
errors: [],
|
|
126
|
+
not_implemented: [],
|
|
125
127
|
...(note ? { note } : {}),
|
|
126
128
|
};
|
|
127
129
|
}
|
|
128
130
|
|
|
129
131
|
function ensureSurfaceSummary(tierSummary, surface) {
|
|
130
132
|
if (!tierSummary.surfaces[surface]) {
|
|
131
|
-
tierSummary.surfaces[surface] = { passed: 0, failed: 0, errored: 0 };
|
|
133
|
+
tierSummary.surfaces[surface] = { passed: 0, failed: 0, errored: 0, not_implemented: 0 };
|
|
132
134
|
}
|
|
133
135
|
return tierSummary.surfaces[surface];
|
|
134
136
|
}
|
|
@@ -149,7 +151,7 @@ function executeFixture(targetRoot, adapterCommand, fixture) {
|
|
|
149
151
|
};
|
|
150
152
|
}
|
|
151
153
|
|
|
152
|
-
if (![0, 1, 2].includes(result.status ?? -1)) {
|
|
154
|
+
if (![0, 1, 2, 3].includes(result.status ?? -1)) {
|
|
153
155
|
return {
|
|
154
156
|
status: 'error',
|
|
155
157
|
message: `Adapter exited with unsupported status ${result.status}`,
|
|
@@ -182,7 +184,7 @@ function executeFixture(targetRoot, adapterCommand, fixture) {
|
|
|
182
184
|
};
|
|
183
185
|
}
|
|
184
186
|
|
|
185
|
-
const expectedExitCode = parsed.status === 'pass' ? 0 : parsed.status === 'fail' ? 1 : 2;
|
|
187
|
+
const expectedExitCode = parsed.status === 'pass' ? 0 : parsed.status === 'fail' ? 1 : parsed.status === 'not_implemented' ? 3 : 2;
|
|
186
188
|
if (result.status !== expectedExitCode) {
|
|
187
189
|
return {
|
|
188
190
|
status: 'error',
|
|
@@ -210,6 +212,17 @@ export function verifyProtocolConformance({
|
|
|
210
212
|
|
|
211
213
|
const resolvedTargetRoot = resolve(targetRoot);
|
|
212
214
|
const capabilities = loadCapabilities(resolvedTargetRoot);
|
|
215
|
+
|
|
216
|
+
// Enforce surface claims when capabilities.surfaces exists and --surface is requested
|
|
217
|
+
if (surface && capabilities.surfaces && typeof capabilities.surfaces === 'object') {
|
|
218
|
+
if (!capabilities.surfaces[surface]) {
|
|
219
|
+
throw new Error(
|
|
220
|
+
`Surface "${surface}" is not claimed in capabilities.json. ` +
|
|
221
|
+
`Claimed surfaces: ${Object.keys(capabilities.surfaces).join(', ')}`
|
|
222
|
+
);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
213
226
|
const fixtureEntries = selectFixtureFiles(fixtureRoot, requestedTier, surface);
|
|
214
227
|
const claimedTiers = new Set(capabilities.tiers);
|
|
215
228
|
const report = {
|
|
@@ -250,6 +263,17 @@ export function verifyProtocolConformance({
|
|
|
250
263
|
continue;
|
|
251
264
|
}
|
|
252
265
|
|
|
266
|
+
if (adapterResult.status === 'not_implemented') {
|
|
267
|
+
tierSummary.fixtures_not_implemented += 1;
|
|
268
|
+
surfaceSummary.not_implemented += 1;
|
|
269
|
+
tierSummary.not_implemented.push({
|
|
270
|
+
fixture_id: fixture.fixture_id,
|
|
271
|
+
surface: fixture.surface,
|
|
272
|
+
message: adapterResult.message || 'Not implemented',
|
|
273
|
+
});
|
|
274
|
+
continue;
|
|
275
|
+
}
|
|
276
|
+
|
|
253
277
|
if (adapterResult.status === 'fail') {
|
|
254
278
|
tierSummary.fixtures_failed += 1;
|
|
255
279
|
surfaceSummary.failed += 1;
|