create-agdf 0.20.0 → 0.20.1
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 +32 -18
- package/generated/plugins/agdf/.claude-plugin/plugin.json +1 -1
- package/generated/plugins/agdf/.codex-plugin/plugin.json +1 -1
- package/generated/plugins/agdf/mcp/server/package.json +2 -2
- package/generated/plugins/agdf/meta/agdf-mcp-capability.json +1 -1
- package/generated/plugins/agdf/meta/agdf-plugin.definition.json +102 -11
- package/generated/plugins/agdf/meta/copilot-payload-baseline.json +2 -2
- package/generated/plugins/agdf/meta/distribution-profile-history.json +7 -0
- package/generated/plugins/agdf/runtime/create-agdf/generated/plugins/agdf/meta/agdf-plugin.definition.json +102 -11
- package/generated/plugins/agdf/runtime/create-agdf/package.json +1 -1
- package/generated/plugins/agdf/runtime/runtime-manifest.json +2 -2
- package/generated/plugins/agdf/submission/openai/availability.md +1 -1
- package/generated/plugins/agdf/submission/openai/capability-matrix.json +1 -1
- package/generated/plugins/agdf/submission/openai/release-notes.md +1 -1
- package/generated/plugins/agdf/submission/openai/reviewer-cases.json +1 -1
- package/generated/plugins/copilot/agdf/.agdf-payload-inventory.json +17 -17
- package/generated/plugins/copilot/agdf/mcp/server/package.json +2 -2
- package/generated/plugins/copilot/agdf/meta/agdf-plugin.definition.json +102 -11
- package/generated/plugins/copilot/agdf/meta/distribution-profile-history.json +7 -0
- package/generated/plugins/copilot/agdf/plugin.json +1 -1
- package/generated/plugins/copilot/agdf/runtime/create-agdf/generated/plugins/agdf/meta/agdf-plugin.definition.json +102 -11
- package/generated/plugins/copilot/agdf/runtime/create-agdf/package.json +1 -1
- package/generated/plugins/copilot/agdf/runtime/runtime-manifest.json +2 -2
- package/generated/submissions/openai/agdf/.codex-plugin/plugin.json +1 -1
- package/generated/submissions/openai/agdf/meta/agdf-plugin.definition.json +102 -11
- package/generated/submissions/openai/agdf/meta/copilot-payload-baseline.json +2 -2
- package/generated/submissions/openai/agdf/meta/distribution-profile-history.json +7 -0
- package/generated/submissions/openai/agdf/plugin.json +1 -1
- package/generated/submissions/openai/agdf/submission/openai/availability.md +1 -1
- package/generated/submissions/openai/agdf/submission/openai/capability-matrix.json +1 -1
- package/generated/submissions/openai/agdf/submission/openai/inventory.json +12 -12
- package/generated/submissions/openai/agdf/submission/openai/listing.json +1 -1
- package/generated/submissions/openai/agdf/submission/openai/readiness.json +2 -2
- package/generated/submissions/openai/agdf/submission/openai/readiness.md +2 -2
- package/generated/submissions/openai/agdf/submission/openai/release-notes.md +1 -1
- package/generated/submissions/openai/agdf/submission/openai/reviewer-cases.json +1 -1
- package/lib/host-adapters/codex/config-source.js +48 -0
- package/lib/mcp-lifecycle/adapters/codex.js +40 -29
- package/package.json +1 -1
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
// A bounded lexical view for the adapter's deliberately narrow TOML readers.
|
|
2
|
+
// Keep UTF-16 offsets and line endings so edits and hashes always use original
|
|
3
|
+
// bytes. Comments and multiline string payloads cannot supply tables, enabled
|
|
4
|
+
// fields or ownership markers. This is not a general TOML parser: unsupported
|
|
5
|
+
// MCP shapes still fail the existing structural/ownership checks.
|
|
6
|
+
export function codexConfigSyntax(content) {
|
|
7
|
+
if (Buffer.byteLength(content) > 65_536) throw Error('AGDF_MCP_CODEX_CONFIG_INVALID');
|
|
8
|
+
const syntax = content.split('');
|
|
9
|
+
const hide = (start, end) => {
|
|
10
|
+
for (let i = start; i < end; i++) if (content[i] !== '\n' && content[i] !== '\r') syntax[i] = ' ';
|
|
11
|
+
};
|
|
12
|
+
for (let i = 0; i < content.length;) {
|
|
13
|
+
if (content[i] === '#') {
|
|
14
|
+
const end = content.indexOf('\n', i);
|
|
15
|
+
hide(i, end < 0 ? content.length : end);
|
|
16
|
+
i = end < 0 ? content.length : end;
|
|
17
|
+
continue;
|
|
18
|
+
}
|
|
19
|
+
const quote = content[i];
|
|
20
|
+
if (quote !== '"' && quote !== "'") { i++; continue; }
|
|
21
|
+
const start = i, multiline = content.startsWith(quote.repeat(3), i);
|
|
22
|
+
i += multiline ? 3 : 1;
|
|
23
|
+
let closed = false;
|
|
24
|
+
while (i < content.length) {
|
|
25
|
+
if (quote === '"' && content[i] === '\\') {
|
|
26
|
+
if (!multiline && /[\r\n]/u.test(content[i + 1] ?? '')) throw Error('AGDF_MCP_CODEX_CONFIG_INVALID');
|
|
27
|
+
i += 2; continue;
|
|
28
|
+
}
|
|
29
|
+
if (!multiline && /[\r\n]/u.test(content[i])) throw Error('AGDF_MCP_CODEX_CONFIG_INVALID');
|
|
30
|
+
if (content[i] !== quote) { i++; continue; }
|
|
31
|
+
if (!multiline) { i++; closed = true; break; }
|
|
32
|
+
let end = i;
|
|
33
|
+
while (content[end] === quote) end++;
|
|
34
|
+
const count = end - i;
|
|
35
|
+
if (count > 5) throw Error('AGDF_MCP_CODEX_CONFIG_INVALID');
|
|
36
|
+
i = end;
|
|
37
|
+
if (count >= 3) { closed = true; break; }
|
|
38
|
+
}
|
|
39
|
+
if (!closed) throw Error('AGDF_MCP_CODEX_CONFIG_INVALID');
|
|
40
|
+
if (multiline) {
|
|
41
|
+
hide(start, i);
|
|
42
|
+
// Keep a non-boolean placeholder so a multiline enabled value is unknown,
|
|
43
|
+
// rather than mistaken for a missing field with its default value.
|
|
44
|
+
syntax[start] = quote; syntax[start + 1] = quote;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return syntax.join('');
|
|
48
|
+
}
|
|
@@ -6,6 +6,7 @@ import { inspectMcpServerPackage, inspectMcpExecutableRoot } from '../package.js
|
|
|
6
6
|
import { homedir } from "node:os";
|
|
7
7
|
import { dirname, basename, join, isAbsolute, resolve, relative, sep } from "node:path";
|
|
8
8
|
import { fileURLToPath } from 'node:url';
|
|
9
|
+
import { codexConfigSyntax } from '../../host-adapters/codex/config-source.js';
|
|
9
10
|
import {
|
|
10
11
|
allSourceResult,
|
|
11
12
|
atomicWrite,
|
|
@@ -49,13 +50,13 @@ function section(spec, { createdConfig = false, createdDirectory = false } = {})
|
|
|
49
50
|
}
|
|
50
51
|
|
|
51
52
|
function sectionRange(content, id = 'agdf') {
|
|
52
|
-
//
|
|
53
|
-
//
|
|
54
|
-
|
|
53
|
+
// Ownership remains limited to generated single-line sections. Ignore table
|
|
54
|
+
// examples inside unrelated TOML strings without rewriting those strings.
|
|
55
|
+
const syntax = codexConfigSyntax(content);
|
|
55
56
|
const escaped = id.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
56
57
|
const exactHeader = `[mcp_servers.${id}]`;
|
|
57
|
-
const headers = [...
|
|
58
|
-
const unsupported =
|
|
58
|
+
const headers = [...syntax.matchAll(new RegExp('^[ \\t]*\\[mcp_servers\\.' + escaped + '\\][ \\t]*\\r?$', 'gm'))];
|
|
59
|
+
const unsupported = syntax.split("\n").some((line) => {
|
|
59
60
|
const trimmed = line.trim();
|
|
60
61
|
if (!trimmed || trimmed.startsWith("#")) return false;
|
|
61
62
|
if (trimmed.startsWith("[")) {
|
|
@@ -71,12 +72,12 @@ function sectionRange(content, id = 'agdf') {
|
|
|
71
72
|
const [header] = headers;
|
|
72
73
|
if (!header) return null;
|
|
73
74
|
const sectionStart = header.index;
|
|
74
|
-
const next = /^[ \t]*\[[^\n]+\][ \t]
|
|
75
|
+
const next = /^[ \t]*\[[^\r\n]+\][ \t]*\r?$/gm;
|
|
75
76
|
next.lastIndex = sectionStart + header[0].length;
|
|
76
|
-
const nextHeader = next.exec(
|
|
77
|
+
const nextHeader = next.exec(syntax);
|
|
77
78
|
let start = sectionStart;
|
|
78
|
-
const marker = content.slice(0, sectionStart).match(/(?:^|\n)(# AGDF-OWNED-MCP: [^\n]+)\n$/);
|
|
79
|
-
if (marker) start = sectionStart - marker[0].length + (marker[0].startsWith(
|
|
79
|
+
const marker = content.slice(0, sectionStart).match(/(?:^|\r?\n)(# AGDF-OWNED-MCP: [^\r\n]+)\r?\n$/);
|
|
80
|
+
if (marker) start = sectionStart - marker[0].length + (marker[0].startsWith('\r\n') ? 2 : marker[0].startsWith('\n') ? 1 : 0);
|
|
80
81
|
return { start, sectionStart, end: nextHeader?.index ?? content.length, marker: marker?.[1] ?? null };
|
|
81
82
|
}
|
|
82
83
|
|
|
@@ -215,11 +216,10 @@ export function inspectCodexSetup({ target, env = {}, pluginRoot } = {}) {
|
|
|
215
216
|
for (const source of sources({ scope: 'project', target, env })) {
|
|
216
217
|
try {
|
|
217
218
|
const snapshot = safeSnapshot(source.path);
|
|
218
|
-
|
|
219
|
-
if (/'''|"""/u.test(snapshot.content)) throw Error('unsupported_multiline_source');
|
|
219
|
+
const syntax = codexConfigSyntax(snapshot.content);
|
|
220
220
|
const sourceDigest = createHash('sha256').update(snapshot.content).digest('hex');
|
|
221
221
|
checked.push({ source: source.id, path: source.path, status: snapshot.existed ? 'declared' : 'absent', digest: sourceDigest });
|
|
222
|
-
const sections = [...
|
|
222
|
+
const sections = [...syntax.matchAll(/^[ \t]*\[([^\r\n]+)\][ \t]*\r?$/gm)];
|
|
223
223
|
for (let index = 0; index < sections.length; index++) {
|
|
224
224
|
const header = sections[index][1];
|
|
225
225
|
const id = /^mcp_servers\.([A-Za-z0-9_-]+)$/u.exec(header)?.[1];
|
|
@@ -227,13 +227,13 @@ export function inspectCodexSetup({ target, env = {}, pluginRoot } = {}) {
|
|
|
227
227
|
if (!id && !plugin) continue;
|
|
228
228
|
if (entries.length >= 32) throw Error('bounded_entries');
|
|
229
229
|
const name = plugin ? 'agdf' : id;
|
|
230
|
-
const body =
|
|
230
|
+
const body = syntax.slice(sections[index].index + sections[index][0].length, sections[index + 1]?.index ?? syntax.length);
|
|
231
231
|
const role = plugin ? 'product' : ['agdf-cockpit', 'agdf-cockpit-local'].includes(name) ? 'cockpit'
|
|
232
232
|
: name.startsWith('agdf-test-') || ['agdf-cockpit-draft-check', 'agdf-decision-probe'].includes(name) ? 'diagnostic' : 'legacy_or_conflict';
|
|
233
233
|
const value = key => new RegExp('^' + key + '[ \\t]*=[ \\t]*([^\\n#]+)', 'm').exec(body)?.[1]?.trim();
|
|
234
234
|
const declaredEnabled = value('enabled');
|
|
235
235
|
const enabled = declaredEnabled === 'false' ? false : declaredEnabled === 'true' ? true : declaredEnabled !== undefined || plugin ? null : true;
|
|
236
|
-
const beforeHeader = snapshot.content.slice(0, sections[index].index).match(/(# AGDF-OWNED-MCP: [^\n]+)\n$/u)?.[1];
|
|
236
|
+
const beforeHeader = snapshot.content.slice(0, sections[index].index).match(/(# AGDF-OWNED-MCP: [^\r\n]+)\r?\n$/u)?.[1];
|
|
237
237
|
const mark = identity(beforeHeader);
|
|
238
238
|
const exactIdOwned = mark && (plugin || name === 'agdf' || mark.server_id === name && mark.role === role);
|
|
239
239
|
const timeout = key => { const raw = value(key); return raw && /^\d+(?:\.\d+)?$/u.test(raw) ? Number(raw) : null; };
|
|
@@ -298,6 +298,24 @@ function mcpTable(header) {
|
|
|
298
298
|
return match ? { name: match[1], nested: Boolean(match[2]) } : null;
|
|
299
299
|
}
|
|
300
300
|
|
|
301
|
+
function mcpTables(syntax) {
|
|
302
|
+
const headers = [...syntax.matchAll(/^[ \t]*\[([^\r\n]+)\][ \t]*\r?$/gm)], tables = [], seen = new Set();
|
|
303
|
+
for (let i = 0; i < headers.length; i++) {
|
|
304
|
+
const header = headers[i][1], normalized = header.replace(/[\s"'\[\]]/gu, '');
|
|
305
|
+
if (normalized !== 'mcp_servers' && !normalized.startsWith('mcp_servers.')) continue;
|
|
306
|
+
const table = mcpTable(header);
|
|
307
|
+
if (!table || seen.has(header)) throw Error('unsupported_mcp_header');
|
|
308
|
+
seen.add(header);
|
|
309
|
+
tables.push({ ...table, bodyStart: headers[i].index + headers[i][0].length,
|
|
310
|
+
end: headers[i + 1]?.index ?? syntax.length });
|
|
311
|
+
}
|
|
312
|
+
if (syntax.split('\n').some(line => {
|
|
313
|
+
const key = line.match(/^[ \t]*([^=\n]+)=/u)?.[1]?.replace(/[\s"']/gu, '');
|
|
314
|
+
return key === 'mcp_servers' || key?.startsWith('mcp_servers.');
|
|
315
|
+
})) throw Error('unsupported_mcp_assignment');
|
|
316
|
+
return tables;
|
|
317
|
+
}
|
|
318
|
+
|
|
301
319
|
export function inspectCodexCockpitPlugin(pluginRoot) {
|
|
302
320
|
try {
|
|
303
321
|
if (!isAbsolute(pluginRoot) || portablePath(realpathSync(pluginRoot)) !== portablePath(pluginRoot)) throw Error('plugin_path_invalid');
|
|
@@ -390,12 +408,10 @@ export function createCodexCockpitTransition({ target, env = {}, serverId: id, r
|
|
|
390
408
|
}
|
|
391
409
|
// No higher/lower scope same key, aliases or second Cockpit is silently adopted.
|
|
392
410
|
for (const source of snapshots) {
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
for (const
|
|
397
|
-
const table = mcpTable(`mcp_servers.${header[1]}`);
|
|
398
|
-
if (!table) throw Error('AGDF_MCP_COCKPIT_INVENTORY_UNCONFIRMED');
|
|
411
|
+
let tables;
|
|
412
|
+
try { tables = mcpTables(codexConfigSyntax(source.content)); }
|
|
413
|
+
catch { throw Error('AGDF_MCP_COCKPIT_INVENTORY_UNCONFIRMED'); }
|
|
414
|
+
for (const table of tables) {
|
|
399
415
|
if ([potentialAlias('agdf-cockpit'), potentialAlias('agdf-cockpit-local')].includes(potentialAlias(table.name))
|
|
400
416
|
&& !(source.path === path && table.name === id && !table.nested)) throw Error('AGDF_MCP_COCKPIT_NAME_CONFLICT');
|
|
401
417
|
}
|
|
@@ -437,23 +453,18 @@ export function inspectCodexCockpitAdmission({ target, env = {}, exec, manifestR
|
|
|
437
453
|
for (const source of sources({ scope: 'project', target, env })) {
|
|
438
454
|
try {
|
|
439
455
|
const snapshot = safeSnapshot(source.path), content = snapshot.content;
|
|
440
|
-
|
|
456
|
+
let syntax;
|
|
457
|
+
try { syntax = codexConfigSyntax(content); } catch { throw Error('unsupported_source'); }
|
|
441
458
|
checked.push({ path: source.path, digest: sha(content) });
|
|
442
|
-
const
|
|
443
|
-
for (let i = 0; i < headers.length; i++) {
|
|
444
|
-
const header = headers[i][1];
|
|
445
|
-
if (!header.replace(/[\s"']/gu, '').startsWith('mcp_servers.')) continue;
|
|
446
|
-
const table = mcpTable(header);
|
|
447
|
-
if (!table) throw Error('unsupported_mcp_header');
|
|
459
|
+
for (const table of mcpTables(syntax)) {
|
|
448
460
|
const name = table.name;
|
|
449
461
|
if (potentialAlias(name) !== 'agdf_cockpit') continue;
|
|
450
462
|
if (table.nested) throw Error('unsupported_mcp_header');
|
|
451
|
-
const body =
|
|
463
|
+
const body = syntax.slice(table.bodyStart, table.end);
|
|
452
464
|
const enabled = [...body.matchAll(/^[ \t]*enabled[ \t]*=[ \t]*([^\n#]+)(?:#[^\n]*)?$/gm)];
|
|
453
465
|
if (enabled.length === 1 && enabled[0][1].trim() === 'false') continue;
|
|
454
466
|
conflicts.push({ path: source.path, server_id: name, reason: 'same_key_or_possible_alias' });
|
|
455
467
|
}
|
|
456
|
-
if (/^[ \t]*mcp_servers(?:[. \t]|=)/mu.test(content)) throw Error('unsupported_mcp_assignment');
|
|
457
468
|
} catch (error) { conflicts.push({ path: source.path, reason: error.message }); }
|
|
458
469
|
}
|
|
459
470
|
let nativeProviderStatus = 'unobserved';
|