@open-agent-toolkit/cli 0.1.50 → 0.1.51
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/assets/agents/oat-phase-implementer.md +16 -5
- package/assets/docs/cli-utilities/workflow-gates.md +1 -1
- package/assets/docs/provider-sync/commands.md +29 -1
- package/assets/docs/provider-sync/providers.md +13 -4
- package/assets/docs/provider-sync/scope-and-surface.md +13 -0
- package/assets/docs/workflows/projects/implementation-execution.md +29 -3
- package/assets/docs/workflows/projects/reviews.md +18 -1
- package/assets/public-package-versions.json +4 -4
- package/assets/skills/oat-agent-instructions-analyze/references/docs/provider-reference.md +8 -2
- package/assets/skills/oat-agent-instructions-apply/references/docs/provider-reference.md +8 -2
- package/assets/skills/oat-project-implement/SKILL.md +93 -38
- package/assets/skills/oat-project-review-provide/SKILL.md +27 -9
- package/dist/commands/doctor/index.d.ts.map +1 -1
- package/dist/commands/doctor/index.js +148 -85
- package/dist/commands/gate/index.js +1 -1
- package/dist/commands/project/dispatch-ceiling/index.d.ts.map +1 -1
- package/dist/commands/project/dispatch-ceiling/index.js +80 -0
- package/dist/commands/providers/codex/materialize.d.ts.map +1 -1
- package/dist/commands/providers/codex/materialize.js +31 -15
- package/dist/providers/codex/codec/config-merge.d.ts +8 -2
- package/dist/providers/codex/codec/config-merge.d.ts.map +1 -1
- package/dist/providers/codex/codec/config-merge.js +17 -2
- package/dist/providers/codex/codec/sync-extension.d.ts.map +1 -1
- package/dist/providers/codex/codec/sync-extension.js +14 -4
- package/package.json +2 -2
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: oat-project-review-provide
|
|
3
|
-
version: 1.3.
|
|
3
|
+
version: 1.3.14
|
|
4
4
|
description: Use when the user explicitly asks to review an OAT project — e.g. "review project", "review the project", "run project review", or confirms a previously offered review. Do NOT auto-invoke on completed work alone. Resolves a project review scope and offers before running.
|
|
5
5
|
disable-model-invocation: false
|
|
6
6
|
user-invocable: true
|
|
@@ -555,13 +555,16 @@ fallbacks.
|
|
|
555
555
|
A concrete managed Codex target takes precedence over tier availability.
|
|
556
556
|
Build the actual provider invocation before reporting the target as enforced:
|
|
557
557
|
|
|
558
|
-
- Codex
|
|
559
|
-
`
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
558
|
+
- Codex must send the resolver-returned Codex variant first as the native
|
|
559
|
+
`agent_type`. Spawn acceptance plus the complete launcher payload is
|
|
560
|
+
configured invocation evidence; it does not require reviewer self-report or
|
|
561
|
+
separate runtime telemetry. A native role-selection rejection means an
|
|
562
|
+
explicit host rejection of that exact `agent_type` before any reviewer or
|
|
563
|
+
child starts. Only after that pre-start rejection may the workflow launch a
|
|
564
|
+
fresh Codex child with the resolver target's explicit model, reasoning
|
|
565
|
+
effort, canonical role instructions from `.agents/agents/oat-reviewer.md`,
|
|
566
|
+
and the same Review Scope payload. If neither exact route is available, use
|
|
567
|
+
only a verified-equivalent inline route or block the review.
|
|
565
568
|
- Claude requires a non-empty `providers.claude.dispatchArgs.model`; the actual
|
|
566
569
|
provider invocation must include that exact value as its `model` argument.
|
|
567
570
|
- Cursor requires a non-empty `providers.cursor.dispatchArgs.model`; the actual
|
|
@@ -573,6 +576,18 @@ candidate ladder, fail closed before review. Route interactive repair through
|
|
|
573
576
|
the planning workflow's `Complete Dispatch Ladder Adoption Contract`; do not
|
|
574
577
|
invent a reviewer target.
|
|
575
578
|
|
|
579
|
+
After constructing the complete provider payload, record the launcher-owned
|
|
580
|
+
`target`, `model_axis`, and `effort_axis` with
|
|
581
|
+
`launcher-selected/config-declared` provenance. These fields are immutable:
|
|
582
|
+
missing telemetry, missing reviewer self-report, or contradictory self-report
|
|
583
|
+
must not populate, replace, or overwrite them and must not trigger fallback.
|
|
584
|
+
|
|
585
|
+
Once the native host accepts a reviewer, every terminal result is an
|
|
586
|
+
authoritative review outcome. An accepted reviewer returning `BLOCKED` is a
|
|
587
|
+
terminal blocking review outcome: it blocks the review and does not invoke or
|
|
588
|
+
trigger the fresh-child fallback. Absent findings from that terminal must not
|
|
589
|
+
be parsed, interpreted, or treated as a passing review.
|
|
590
|
+
|
|
576
591
|
On timeout or retry, reuse the same exact role or complete invocation payload,
|
|
577
592
|
including the Claude or Cursor model argument. If the host cannot apply a
|
|
578
593
|
required role or model argument, fail closed or block unless inline execution
|
|
@@ -623,7 +638,7 @@ Then spawn the reviewer:
|
|
|
623
638
|
- Use provider-appropriate dispatch:
|
|
624
639
|
- Claude Code: Task tool with `subagent_type: "oat-reviewer"` (resolves from `.claude/agents/oat-reviewer.md`). For a concrete managed target, the payload must also contain `model: providers.claude.dispatchArgs.model` with the resolver-returned value.
|
|
625
640
|
- Cursor: explicit invocation `/oat-reviewer` (or natural mention) with agent resolved from `.cursor/agents/oat-reviewer.md` or `.claude/agents/oat-reviewer.md` compatibility path. For a concrete managed target, the invocation must also contain `model: providers.cursor.dispatchArgs.model` with the exact opaque resolver-returned string.
|
|
626
|
-
- Codex style: for a concrete managed target, spawn the exact resolver-returned `agent_type`;
|
|
641
|
+
- Codex style: for a concrete managed target, first spawn the exact resolver-returned native `agent_type`; only an explicit pre-start native role-selection rejection permits the explicitly pinned fresh-child route from Step 6.0. Generic auto-selection is permitted only for the documented base-role exceptions.
|
|
627
642
|
- Pass the Review Scope metadata block from Step 5 as the prompt
|
|
628
643
|
- Include the pre-computed artifact path for the subagent to write to
|
|
629
644
|
- **If a worktree was resolved in Step 1.5:** include the worktree path in the prompt so the subagent writes the artifact to the worktree directory, not the current session's working directory
|
|
@@ -633,6 +648,9 @@ The `oat-reviewer` agent definition contains the full review process, mode contr
|
|
|
633
648
|
|
|
634
649
|
After the subagent completes:
|
|
635
650
|
|
|
651
|
+
- Treat its terminal status as authoritative. An accepted `BLOCKED` result
|
|
652
|
+
blocks the review; do not invoke fallback and do not infer a pass from a
|
|
653
|
+
missing review artifact or absent findings.
|
|
636
654
|
- Verify the review artifact was written to the expected path
|
|
637
655
|
- Continue with Step 9 (plan update) and Step 9.5 (commit)
|
|
638
656
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/doctor/index.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/doctor/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { access, mkdtemp, readdir, readFile, rm, symlink, } from 'node:fs/promises';
|
|
2
2
|
import { tmpdir } from 'node:os';
|
|
3
|
-
import { join } from 'node:path';
|
|
3
|
+
import { dirname, join } from 'node:path';
|
|
4
4
|
import { buildCommandContext, } from '../../app/command-context.js';
|
|
5
5
|
import { compareVersions } from '../init/tools/shared/version.js';
|
|
6
6
|
import { createPjmDisabledCheck, runPjmDoctorChecks, } from '../pjm/doctor.js';
|
|
@@ -279,6 +279,152 @@ async function isManagedCodexRoleConfig(scopeRoot, roleName, configFile, depende
|
|
|
279
279
|
return false;
|
|
280
280
|
}
|
|
281
281
|
}
|
|
282
|
+
function getCodexAgents(config) {
|
|
283
|
+
const agents = config.agents;
|
|
284
|
+
return agents && typeof agents === 'object' && !Array.isArray(agents)
|
|
285
|
+
? agents
|
|
286
|
+
: {};
|
|
287
|
+
}
|
|
288
|
+
function getCodexMaxDepthEntry(config) {
|
|
289
|
+
const agents = getCodexAgents(config);
|
|
290
|
+
return {
|
|
291
|
+
present: Object.prototype.hasOwnProperty.call(agents, 'max_depth'),
|
|
292
|
+
value: agents.max_depth,
|
|
293
|
+
};
|
|
294
|
+
}
|
|
295
|
+
/**
|
|
296
|
+
* Applies Codex config precedence without letting an invalid project value fall
|
|
297
|
+
* through to the lower-precedence user value.
|
|
298
|
+
*/
|
|
299
|
+
async function resolveDoctorCodexMaxDepth(scope, parsedConfig, userHome, dependencies) {
|
|
300
|
+
const scopedEntry = getCodexMaxDepthEntry(parsedConfig);
|
|
301
|
+
if (scope !== 'project' || scopedEntry.present) {
|
|
302
|
+
return scopedEntry;
|
|
303
|
+
}
|
|
304
|
+
const userConfigPath = join(userHome, '.codex', 'config.toml');
|
|
305
|
+
if (!(await dependencies.pathExists(userConfigPath))) {
|
|
306
|
+
return scopedEntry;
|
|
307
|
+
}
|
|
308
|
+
try {
|
|
309
|
+
return getCodexMaxDepthEntry(TOML.parse(await dependencies.readFile(userConfigPath)));
|
|
310
|
+
}
|
|
311
|
+
catch {
|
|
312
|
+
return { present: true, value: null };
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
function createCodexMaxDepthCheck(scope, entry) {
|
|
316
|
+
const topology = 'root (0) → phase coordinator (1) → task worker (2)';
|
|
317
|
+
const numericDepth = typeof entry.value === 'number' && Number.isFinite(entry.value)
|
|
318
|
+
? entry.value
|
|
319
|
+
: null;
|
|
320
|
+
const sufficient = numericDepth !== null && numericDepth >= 2;
|
|
321
|
+
let state;
|
|
322
|
+
if (!entry.present) {
|
|
323
|
+
state = 'agents.max_depth is missing';
|
|
324
|
+
}
|
|
325
|
+
else if (numericDepth === null) {
|
|
326
|
+
state = 'agents.max_depth is not a valid number';
|
|
327
|
+
}
|
|
328
|
+
else {
|
|
329
|
+
state = `agents.max_depth is ${numericDepth}`;
|
|
330
|
+
}
|
|
331
|
+
return {
|
|
332
|
+
name: `${scope}:codex_max_depth`,
|
|
333
|
+
description: 'Codex managed-role nested dispatch depth',
|
|
334
|
+
status: sufficient ? 'pass' : 'warn',
|
|
335
|
+
message: sufficient
|
|
336
|
+
? `${state}; sufficient for ${topology}.`
|
|
337
|
+
: `${state}; OAT managed implementation requires ${topology}.`,
|
|
338
|
+
fix: sufficient
|
|
339
|
+
? undefined
|
|
340
|
+
: `Run \`oat sync --scope ${scope}\`, or materialize a single role with \`oat providers codex materialize <agent-name> --model <model> --effort <effort> --scope ${scope}\`.`,
|
|
341
|
+
};
|
|
342
|
+
}
|
|
343
|
+
async function runCodexChecksForScope(scope, scopeRoot, userHome, dependencies) {
|
|
344
|
+
const checks = [];
|
|
345
|
+
const codexConfigPath = join(scopeRoot, '.codex', 'config.toml');
|
|
346
|
+
if (!(await dependencies.pathExists(codexConfigPath))) {
|
|
347
|
+
return checks;
|
|
348
|
+
}
|
|
349
|
+
let parsedConfig;
|
|
350
|
+
try {
|
|
351
|
+
parsedConfig = TOML.parse(await dependencies.readFile(codexConfigPath));
|
|
352
|
+
checks.push({
|
|
353
|
+
name: `${scope}:codex_config_toml`,
|
|
354
|
+
description: 'Codex config TOML parseability',
|
|
355
|
+
status: 'pass',
|
|
356
|
+
message: '.codex/config.toml parsed successfully.',
|
|
357
|
+
});
|
|
358
|
+
}
|
|
359
|
+
catch (error) {
|
|
360
|
+
checks.push({
|
|
361
|
+
name: `${scope}:codex_config_toml`,
|
|
362
|
+
description: 'Codex config TOML parseability',
|
|
363
|
+
status: 'fail',
|
|
364
|
+
message: error instanceof Error
|
|
365
|
+
? `Failed to parse .codex/config.toml: ${error.message}`
|
|
366
|
+
: 'Failed to parse .codex/config.toml.',
|
|
367
|
+
fix: 'Repair .codex/config.toml syntax and rerun doctor.',
|
|
368
|
+
});
|
|
369
|
+
return checks;
|
|
370
|
+
}
|
|
371
|
+
const features = parsedConfig.features &&
|
|
372
|
+
typeof parsedConfig.features === 'object' &&
|
|
373
|
+
!Array.isArray(parsedConfig.features)
|
|
374
|
+
? parsedConfig.features
|
|
375
|
+
: null;
|
|
376
|
+
const agents = getCodexAgents(parsedConfig);
|
|
377
|
+
const managedRoles = [];
|
|
378
|
+
const roleConfigFiles = new Map();
|
|
379
|
+
for (const [roleName, roleConfig] of Object.entries(agents)) {
|
|
380
|
+
const configFile = getCodexAgentConfigFile(roleConfig);
|
|
381
|
+
if (!configFile) {
|
|
382
|
+
continue;
|
|
383
|
+
}
|
|
384
|
+
roleConfigFiles.set(roleName, configFile);
|
|
385
|
+
if (await isManagedCodexRoleConfig(scopeRoot, roleName, configFile, dependencies)) {
|
|
386
|
+
managedRoles.push(roleName);
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
if (managedRoles.length === 0) {
|
|
390
|
+
return checks;
|
|
391
|
+
}
|
|
392
|
+
const multiAgentEnabled = features?.multi_agent === true || features?.multi_agent === 'true';
|
|
393
|
+
checks.push({
|
|
394
|
+
name: `${scope}:codex_multi_agent`,
|
|
395
|
+
description: 'Codex multi-agent feature flag',
|
|
396
|
+
status: multiAgentEnabled ? 'pass' : 'warn',
|
|
397
|
+
message: multiAgentEnabled
|
|
398
|
+
? 'features.multi_agent is enabled for codex managed roles.'
|
|
399
|
+
: 'Codex managed roles detected but features.multi_agent is not true.',
|
|
400
|
+
fix: multiAgentEnabled
|
|
401
|
+
? undefined
|
|
402
|
+
: 'Set [features] multi_agent = true in .codex/config.toml.',
|
|
403
|
+
});
|
|
404
|
+
checks.push(createCodexMaxDepthCheck(scope, await resolveDoctorCodexMaxDepth(scope, parsedConfig, userHome, dependencies)));
|
|
405
|
+
const missingRoleFiles = [];
|
|
406
|
+
for (const roleName of managedRoles) {
|
|
407
|
+
const configFile = roleConfigFiles.get(roleName);
|
|
408
|
+
if (!configFile)
|
|
409
|
+
continue;
|
|
410
|
+
const absoluteRolePath = join(scopeRoot, '.codex', configFile);
|
|
411
|
+
if (!(await dependencies.pathExists(absoluteRolePath))) {
|
|
412
|
+
missingRoleFiles.push(configFile);
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
checks.push({
|
|
416
|
+
name: `${scope}:codex_role_file_refs`,
|
|
417
|
+
description: 'Codex role config_file references',
|
|
418
|
+
status: missingRoleFiles.length === 0 ? 'pass' : 'warn',
|
|
419
|
+
message: missingRoleFiles.length === 0
|
|
420
|
+
? 'All codex role config_file references exist.'
|
|
421
|
+
: `Missing codex role files: ${missingRoleFiles.join(', ')}`,
|
|
422
|
+
fix: missingRoleFiles.length === 0
|
|
423
|
+
? undefined
|
|
424
|
+
: `Regenerate codex roles with \`oat sync --scope ${scope}\`, or materialize a single role with \`oat providers codex materialize <agent-name> --model <model> --effort <effort> --scope ${scope}\`.`,
|
|
425
|
+
});
|
|
426
|
+
return checks;
|
|
427
|
+
}
|
|
282
428
|
async function runChecksForScope(scope, scopeRoot, userConfigDir, dependencies) {
|
|
283
429
|
const checks = [];
|
|
284
430
|
const skillsPath = join(scopeRoot, '.agents', 'skills');
|
|
@@ -354,6 +500,7 @@ async function runChecksForScope(scope, scopeRoot, userConfigDir, dependencies)
|
|
|
354
500
|
? undefined
|
|
355
501
|
: 'Install or enable a provider directory (e.g. .claude, .cursor, .codex).',
|
|
356
502
|
});
|
|
503
|
+
checks.push(...(await runCodexChecksForScope(scope, scopeRoot, dirname(userConfigDir), dependencies)));
|
|
357
504
|
if (scope === 'project') {
|
|
358
505
|
try {
|
|
359
506
|
const assetsRoot = await dependencies.resolveAssetsRoot();
|
|
@@ -403,90 +550,6 @@ async function runChecksForScope(scope, scopeRoot, userConfigDir, dependencies)
|
|
|
403
550
|
fix: 'Run `pnpm build` and rerun `oat doctor`.',
|
|
404
551
|
});
|
|
405
552
|
}
|
|
406
|
-
const codexConfigPath = join(scopeRoot, '.codex', 'config.toml');
|
|
407
|
-
const codexConfigExists = await dependencies.pathExists(codexConfigPath);
|
|
408
|
-
if (codexConfigExists) {
|
|
409
|
-
let parsedConfig = null;
|
|
410
|
-
try {
|
|
411
|
-
parsedConfig = TOML.parse(await dependencies.readFile(codexConfigPath));
|
|
412
|
-
checks.push({
|
|
413
|
-
name: `${scope}:codex_config_toml`,
|
|
414
|
-
description: 'Codex config TOML parseability',
|
|
415
|
-
status: 'pass',
|
|
416
|
-
message: '.codex/config.toml parsed successfully.',
|
|
417
|
-
});
|
|
418
|
-
}
|
|
419
|
-
catch (error) {
|
|
420
|
-
checks.push({
|
|
421
|
-
name: `${scope}:codex_config_toml`,
|
|
422
|
-
description: 'Codex config TOML parseability',
|
|
423
|
-
status: 'fail',
|
|
424
|
-
message: error instanceof Error
|
|
425
|
-
? `Failed to parse .codex/config.toml: ${error.message}`
|
|
426
|
-
: 'Failed to parse .codex/config.toml.',
|
|
427
|
-
fix: 'Repair .codex/config.toml syntax and rerun doctor.',
|
|
428
|
-
});
|
|
429
|
-
}
|
|
430
|
-
if (parsedConfig) {
|
|
431
|
-
const features = parsedConfig.features &&
|
|
432
|
-
typeof parsedConfig.features === 'object' &&
|
|
433
|
-
!Array.isArray(parsedConfig.features)
|
|
434
|
-
? parsedConfig.features
|
|
435
|
-
: null;
|
|
436
|
-
const agents = parsedConfig.agents &&
|
|
437
|
-
typeof parsedConfig.agents === 'object' &&
|
|
438
|
-
!Array.isArray(parsedConfig.agents)
|
|
439
|
-
? parsedConfig.agents
|
|
440
|
-
: null;
|
|
441
|
-
const managedRoles = [];
|
|
442
|
-
const roleConfigFiles = new Map();
|
|
443
|
-
for (const [roleName, roleConfig] of Object.entries(agents ?? {})) {
|
|
444
|
-
const configFile = getCodexAgentConfigFile(roleConfig);
|
|
445
|
-
if (!configFile) {
|
|
446
|
-
continue;
|
|
447
|
-
}
|
|
448
|
-
roleConfigFiles.set(roleName, configFile);
|
|
449
|
-
if (await isManagedCodexRoleConfig(scopeRoot, roleName, configFile, dependencies)) {
|
|
450
|
-
managedRoles.push(roleName);
|
|
451
|
-
}
|
|
452
|
-
}
|
|
453
|
-
if (managedRoles.length > 0) {
|
|
454
|
-
const multiAgentEnabled = features?.multi_agent === true || features?.multi_agent === 'true';
|
|
455
|
-
checks.push({
|
|
456
|
-
name: `${scope}:codex_multi_agent`,
|
|
457
|
-
description: 'Codex multi-agent feature flag',
|
|
458
|
-
status: multiAgentEnabled ? 'pass' : 'warn',
|
|
459
|
-
message: multiAgentEnabled
|
|
460
|
-
? 'features.multi_agent is enabled for codex managed roles.'
|
|
461
|
-
: 'Codex managed roles detected but features.multi_agent is not true.',
|
|
462
|
-
fix: multiAgentEnabled
|
|
463
|
-
? undefined
|
|
464
|
-
: 'Set [features] multi_agent = true in .codex/config.toml.',
|
|
465
|
-
});
|
|
466
|
-
const missingRoleFiles = [];
|
|
467
|
-
for (const roleName of managedRoles) {
|
|
468
|
-
const configFile = roleConfigFiles.get(roleName);
|
|
469
|
-
if (!configFile)
|
|
470
|
-
continue;
|
|
471
|
-
const absoluteRolePath = join(scopeRoot, '.codex', configFile);
|
|
472
|
-
if (!(await dependencies.pathExists(absoluteRolePath))) {
|
|
473
|
-
missingRoleFiles.push(configFile);
|
|
474
|
-
}
|
|
475
|
-
}
|
|
476
|
-
checks.push({
|
|
477
|
-
name: `${scope}:codex_role_file_refs`,
|
|
478
|
-
description: 'Codex role config_file references',
|
|
479
|
-
status: missingRoleFiles.length === 0 ? 'pass' : 'warn',
|
|
480
|
-
message: missingRoleFiles.length === 0
|
|
481
|
-
? 'All codex role config_file references exist.'
|
|
482
|
-
: `Missing codex role files: ${missingRoleFiles.join(', ')}`,
|
|
483
|
-
fix: missingRoleFiles.length === 0
|
|
484
|
-
? undefined
|
|
485
|
-
: 'Regenerate codex roles with `oat sync --scope project`, or materialize a single role with `oat providers codex materialize ...`.',
|
|
486
|
-
});
|
|
487
|
-
}
|
|
488
|
-
}
|
|
489
|
-
}
|
|
490
553
|
const repoReferenceRoot = join(scopeRoot, '.oat', 'repo');
|
|
491
554
|
const [userConfig, config, localConfig] = await Promise.all([
|
|
492
555
|
dependencies.readUserConfig(userConfigDir),
|
|
@@ -55,7 +55,7 @@ const VALID_IDENTITY_PROVENANCES = [
|
|
|
55
55
|
];
|
|
56
56
|
const REVIEW_GATE_CONTEXT_NOTE = 'This review is gate-originated. If you run `oat-project-review-provide`, set `oat_review_invocation: gate` in the review artifact. Write a canonical review artifact with `### Critical`, `### Important`, `### Medium`, and `### Minor` headings in that order, using `None` for empty sections.';
|
|
57
57
|
const GATE_CHECK_TIMEOUT_MS = 5_000;
|
|
58
|
-
const GATE_EXEC_TIMEOUT_MS =
|
|
58
|
+
const GATE_EXEC_TIMEOUT_MS = 15 * 60 * 1_000;
|
|
59
59
|
function reviewGateProjectContext(project) {
|
|
60
60
|
return [
|
|
61
61
|
`Resolved OAT project path: ${project.path}. Run the review for this project path.`,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/commands/project/dispatch-ceiling/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAEL,KAAK,cAAc,EACnB,KAAK,aAAa,EACnB,MAAM,sBAAsB,CAAC;AAa9B,OAAO,EAUL,KAAK,uBAAuB,EAY7B,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAEL,KAAK,cAAc,EAEpB,MAAM,iBAAiB,CAAC;AAsBzB,OAAO,EAAE,OAAO,EAAU,MAAM,WAAW,CAAC;AAiC5C,UAAU,2BAA2B;IACnC,mBAAmB,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,cAAc,CAAC;IAChE,kBAAkB,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACrD,sBAAsB,EAAE,CACtB,QAAQ,EAAE,MAAM,EAChB,aAAa,EAAE,MAAM,EACrB,GAAG,EAAE,MAAM,CAAC,UAAU,KACnB,OAAO,CAAC,cAAc,CAAC,CAAC;IAC7B,oBAAoB,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,uBAAuB,CAAC,CAAC;IAC7E,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IAC5C,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAC/C,UAAU,EAAE,MAAM,CAAC,UAAU,CAAC;CAC/B;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/commands/project/dispatch-ceiling/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAEL,KAAK,cAAc,EACnB,KAAK,aAAa,EACnB,MAAM,sBAAsB,CAAC;AAa9B,OAAO,EAUL,KAAK,uBAAuB,EAY7B,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAEL,KAAK,cAAc,EAEpB,MAAM,iBAAiB,CAAC;AAsBzB,OAAO,EAAE,OAAO,EAAU,MAAM,WAAW,CAAC;AAiC5C,UAAU,2BAA2B;IACnC,mBAAmB,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,cAAc,CAAC;IAChE,kBAAkB,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACrD,sBAAsB,EAAE,CACtB,QAAQ,EAAE,MAAM,EAChB,aAAa,EAAE,MAAM,EACrB,GAAG,EAAE,MAAM,CAAC,UAAU,KACnB,OAAO,CAAC,cAAc,CAAC,CAAC;IAC7B,oBAAoB,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,uBAAuB,CAAC,CAAC;IAC7E,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IAC5C,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAC/C,UAAU,EAAE,MAAM,CAAC,UAAU,CAAC;CAC/B;AAi/ED,wBAAgB,mCAAmC,CACjD,SAAS,GAAE,OAAO,CAAC,2BAA2B,CAAM,GACnD,OAAO,CAkGT"}
|
|
@@ -1175,6 +1175,58 @@ function readCodexDefaultFromToml(content) {
|
|
|
1175
1175
|
const value = parsed['model_reasoning_effort'];
|
|
1176
1176
|
return typeof value === 'string' && value.trim() ? value.trim() : null;
|
|
1177
1177
|
}
|
|
1178
|
+
function readCodexMaxDepthEntry(content) {
|
|
1179
|
+
let parsed;
|
|
1180
|
+
try {
|
|
1181
|
+
parsed = TOML.parse(content);
|
|
1182
|
+
}
|
|
1183
|
+
catch {
|
|
1184
|
+
return { present: true, value: null };
|
|
1185
|
+
}
|
|
1186
|
+
const agents = parsed.agents;
|
|
1187
|
+
if (!agents || typeof agents !== 'object' || Array.isArray(agents)) {
|
|
1188
|
+
return { present: false, value: undefined };
|
|
1189
|
+
}
|
|
1190
|
+
const record = agents;
|
|
1191
|
+
return {
|
|
1192
|
+
present: Object.prototype.hasOwnProperty.call(record, 'max_depth'),
|
|
1193
|
+
value: record.max_depth,
|
|
1194
|
+
};
|
|
1195
|
+
}
|
|
1196
|
+
async function readCodexMaxDepthAtPath(path, dependencies) {
|
|
1197
|
+
if (!(await dependencies.pathExists(path))) {
|
|
1198
|
+
return { present: false, value: undefined };
|
|
1199
|
+
}
|
|
1200
|
+
try {
|
|
1201
|
+
return readCodexMaxDepthEntry(await dependencies.readFile(path));
|
|
1202
|
+
}
|
|
1203
|
+
catch {
|
|
1204
|
+
return { present: true, value: null };
|
|
1205
|
+
}
|
|
1206
|
+
}
|
|
1207
|
+
/**
|
|
1208
|
+
* Resolves the depth seen by Codex: project config wins whenever it declares a
|
|
1209
|
+
* value, while an absent project value inherits the user config.
|
|
1210
|
+
*/
|
|
1211
|
+
async function resolveEffectiveCodexMaxDepth(scope, repoRoot, context, dependencies) {
|
|
1212
|
+
const userPath = join(context.home, '.codex', 'config.toml');
|
|
1213
|
+
if (scope === 'user') {
|
|
1214
|
+
return readCodexMaxDepthAtPath(userPath, dependencies);
|
|
1215
|
+
}
|
|
1216
|
+
const projectEntry = await readCodexMaxDepthAtPath(join(repoRoot, '.codex', 'config.toml'), dependencies);
|
|
1217
|
+
return projectEntry.present
|
|
1218
|
+
? projectEntry
|
|
1219
|
+
: readCodexMaxDepthAtPath(userPath, dependencies);
|
|
1220
|
+
}
|
|
1221
|
+
function managedCodexDepthBlockMessage(scope, entry) {
|
|
1222
|
+
const validDepth = typeof entry.value === 'number' && Number.isFinite(entry.value);
|
|
1223
|
+
const state = !entry.present
|
|
1224
|
+
? 'agents.max_depth is missing'
|
|
1225
|
+
: validDepth
|
|
1226
|
+
? `agents.max_depth is ${entry.value}`
|
|
1227
|
+
: 'agents.max_depth is not a valid number';
|
|
1228
|
+
return `BLOCKED: Codex ${state}; managed implementation requires root (0) → phase coordinator (1) → task worker (2).\nRun \`oat sync --scope ${scope}\`, or materialize a single role with \`oat providers codex materialize <agent-name> --model <model> --effort <effort> --scope ${scope}\`.`;
|
|
1229
|
+
}
|
|
1178
1230
|
async function resolveCodexProviderDefaultEffort(repoRoot, context, dependencies) {
|
|
1179
1231
|
const candidates = [
|
|
1180
1232
|
join(repoRoot, '.codex', 'config.toml'),
|
|
@@ -1224,6 +1276,34 @@ async function resolveDispatchCeiling(context, dependencies, options) {
|
|
|
1224
1276
|
[provider]: providerResolution,
|
|
1225
1277
|
};
|
|
1226
1278
|
if (resolvedValue) {
|
|
1279
|
+
const requiresManagedCodexDepth = options.preflight === true &&
|
|
1280
|
+
provider === 'codex' &&
|
|
1281
|
+
role === 'implementer' &&
|
|
1282
|
+
resolvedValue.mode === 'managed';
|
|
1283
|
+
if (requiresManagedCodexDepth) {
|
|
1284
|
+
const scope = context.scope === 'user' ? 'user' : 'project';
|
|
1285
|
+
const depth = await resolveEffectiveCodexMaxDepth(scope, repoRoot, context, dependencies);
|
|
1286
|
+
const numericDepth = typeof depth.value === 'number' && Number.isFinite(depth.value)
|
|
1287
|
+
? depth.value
|
|
1288
|
+
: null;
|
|
1289
|
+
if (numericDepth === null || numericDepth < 2) {
|
|
1290
|
+
return {
|
|
1291
|
+
status: 'blocked',
|
|
1292
|
+
provider,
|
|
1293
|
+
value: resolvedValue.value,
|
|
1294
|
+
policyMode: resolvedValue.mode,
|
|
1295
|
+
policy: resolvedValue.policy,
|
|
1296
|
+
source: resolvedValue.source,
|
|
1297
|
+
preset: resolvedValue.preset,
|
|
1298
|
+
unresolved: true,
|
|
1299
|
+
projectPath,
|
|
1300
|
+
providerDefaultEffort,
|
|
1301
|
+
matrix: resolvedValue.matrix,
|
|
1302
|
+
providers,
|
|
1303
|
+
message: managedCodexDepthBlockMessage(scope, depth),
|
|
1304
|
+
};
|
|
1305
|
+
}
|
|
1306
|
+
}
|
|
1227
1307
|
const incompleteManagedPreflight = options.preflight === true &&
|
|
1228
1308
|
resolvedValue.mode === 'managed' &&
|
|
1229
1309
|
providerResolution.mode === 'advisory' &&
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"materialize.d.ts","sourceRoot":"","sources":["../../../../src/commands/providers/codex/materialize.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EACV,sBAAsB,EACtB,qCAAqC,EACtC,MAAM,qCAAqC,CAAC;
|
|
1
|
+
{"version":3,"file":"materialize.d.ts","sourceRoot":"","sources":["../../../../src/commands/providers/codex/materialize.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EACV,sBAAsB,EACtB,qCAAqC,EACtC,MAAM,qCAAqC,CAAC;AAa7C,OAAO,EAAE,OAAO,EAAU,MAAM,WAAW,CAAC;AAyD5C,wBAAgB,4BAA4B,CAC1C,MAAM,EAAE,sBAAsB,GAC7B,MAAM,CAaR;AAsID,wBAAgB,6BAA6B,CAC3C,SAAS,GAAE,OAAO,CAAC,qCAAqC,CAAM,GAC7D,OAAO,CAoCT"}
|
|
@@ -6,7 +6,7 @@ import { readGlobalOptions } from '../../shared/shared.utils.js';
|
|
|
6
6
|
import { CliError } from '../../../errors/index.js';
|
|
7
7
|
import { ensureDir, fileExists } from '../../../fs/io.js';
|
|
8
8
|
import { resolveProjectRoot, resolveScopeRoot } from '../../../fs/paths.js';
|
|
9
|
-
import { mergeCodexConfigForRole } from '../../../providers/codex/codec/config-merge.js';
|
|
9
|
+
import { mergeCodexConfigForRole, readCodexMaxDepth, } from '../../../providers/codex/codec/config-merge.js';
|
|
10
10
|
import { materializeCodexRole } from '../../../providers/codex/codec/materialize.js';
|
|
11
11
|
import { withOatManagedCodexRoleOwner } from '../../../providers/codex/codec/shared.js';
|
|
12
12
|
import { Command, Option } from 'commander';
|
|
@@ -72,8 +72,29 @@ async function buildCodexMaterializePlan(agentName, options, context, dependenci
|
|
|
72
72
|
};
|
|
73
73
|
const rolePath = join(scopeRoot, '.codex', role.configFile);
|
|
74
74
|
const configPath = join(scopeRoot, '.codex', 'config.toml');
|
|
75
|
+
const existingRoleContent = await readOptionalFile(rolePath);
|
|
76
|
+
const existingConfigContent = await readOptionalFile(configPath);
|
|
77
|
+
let inheritedMaxDepth;
|
|
78
|
+
if (scope === 'project') {
|
|
79
|
+
const userScopeRoot = await dependencies.resolveScopeRoot('user', context);
|
|
80
|
+
const userConfigContent = await readOptionalFile(join(userScopeRoot, '.codex', 'config.toml'));
|
|
81
|
+
inheritedMaxDepth = readCodexMaxDepth(userConfigContent) ?? undefined;
|
|
82
|
+
}
|
|
83
|
+
const mergedConfig = mergeCodexConfigForRole({
|
|
84
|
+
existingContent: existingConfigContent,
|
|
85
|
+
role: {
|
|
86
|
+
roleName: role.roleName,
|
|
87
|
+
description: role.description,
|
|
88
|
+
configFile: role.configFile,
|
|
89
|
+
},
|
|
90
|
+
inheritedMaxDepth,
|
|
91
|
+
});
|
|
75
92
|
return {
|
|
93
|
+
configChanged: mergedConfig.changed,
|
|
94
|
+
mergedConfigContent: mergedConfig.mergedContent,
|
|
76
95
|
role,
|
|
96
|
+
roleChanged: existingRoleContent === null ||
|
|
97
|
+
existingRoleContent.trimEnd() !== role.content.trimEnd(),
|
|
77
98
|
result: {
|
|
78
99
|
status: context.dryRun ? 'preview' : 'written',
|
|
79
100
|
dryRun: context.dryRun,
|
|
@@ -93,20 +114,15 @@ async function readOptionalFile(filePath) {
|
|
|
93
114
|
}
|
|
94
115
|
return readFile(filePath, 'utf8');
|
|
95
116
|
}
|
|
96
|
-
async function applyCodexMaterializePlan({ result, role, }) {
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
configFile: role.configFile,
|
|
106
|
-
},
|
|
107
|
-
});
|
|
108
|
-
await ensureDir(dirname(result.configPath));
|
|
109
|
-
await writeFile(result.configPath, mergedConfig.mergedContent, 'utf8');
|
|
117
|
+
async function applyCodexMaterializePlan({ configChanged, mergedConfigContent, result, role, roleChanged, }) {
|
|
118
|
+
if (roleChanged) {
|
|
119
|
+
await ensureDir(dirname(result.rolePath));
|
|
120
|
+
await writeFile(result.rolePath, role.content, 'utf8');
|
|
121
|
+
}
|
|
122
|
+
if (configChanged) {
|
|
123
|
+
await ensureDir(dirname(result.configPath));
|
|
124
|
+
await writeFile(result.configPath, mergedConfigContent, 'utf8');
|
|
125
|
+
}
|
|
110
126
|
}
|
|
111
127
|
async function runCodexMaterializeCommand(agentName, options, context, dependencies) {
|
|
112
128
|
try {
|
|
@@ -7,17 +7,23 @@ export interface CodexConfigMergeArgs {
|
|
|
7
7
|
existingContent: string | null;
|
|
8
8
|
desiredRoles: CodexManagedRoleConfig[];
|
|
9
9
|
staleManagedRoles?: string[];
|
|
10
|
+
inheritedMaxDepth?: number;
|
|
10
11
|
}
|
|
11
12
|
export interface CodexSingleRoleConfigMergeArgs {
|
|
12
13
|
existingContent: string | null;
|
|
13
14
|
role: CodexManagedRoleConfig;
|
|
14
15
|
staleManagedRoles?: string[];
|
|
16
|
+
inheritedMaxDepth?: number;
|
|
15
17
|
}
|
|
16
18
|
export interface CodexConfigMergeResult {
|
|
17
19
|
mergedContent: string;
|
|
18
20
|
changed: boolean;
|
|
19
21
|
removedRoles: string[];
|
|
20
22
|
}
|
|
21
|
-
|
|
22
|
-
export declare function
|
|
23
|
+
/** Reads a valid numeric agents.max_depth value from Codex TOML content. */
|
|
24
|
+
export declare function readCodexMaxDepth(content: string | null): number | null;
|
|
25
|
+
/** Merges managed Codex roles and required shared agent configuration. */
|
|
26
|
+
export declare function mergeCodexConfig({ existingContent, desiredRoles, staleManagedRoles, inheritedMaxDepth, }: CodexConfigMergeArgs): CodexConfigMergeResult;
|
|
27
|
+
/** Merges one managed Codex role using the shared configuration contract. */
|
|
28
|
+
export declare function mergeCodexConfigForRole({ existingContent, role, staleManagedRoles, inheritedMaxDepth, }: CodexSingleRoleConfigMergeArgs): CodexConfigMergeResult;
|
|
23
29
|
//# sourceMappingURL=config-merge.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config-merge.d.ts","sourceRoot":"","sources":["../../../../src/providers/codex/codec/config-merge.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,sBAAsB;IACrC,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,oBAAoB;IACnC,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,YAAY,EAAE,sBAAsB,EAAE,CAAC;IACvC,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"config-merge.d.ts","sourceRoot":"","sources":["../../../../src/providers/codex/codec/config-merge.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,sBAAsB;IACrC,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,oBAAoB;IACnC,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,YAAY,EAAE,sBAAsB,EAAE,CAAC;IACvC,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC7B,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,8BAA8B;IAC7C,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,IAAI,EAAE,sBAAsB,CAAC;IAC7B,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC7B,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,sBAAsB;IACrC,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,OAAO,CAAC;IACjB,YAAY,EAAE,MAAM,EAAE,CAAC;CACxB;AAqCD,4EAA4E;AAC5E,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,CAIvE;AAED,0EAA0E;AAC1E,wBAAgB,gBAAgB,CAAC,EAC/B,eAAe,EACf,YAAY,EACZ,iBAAsB,EACtB,iBAAiB,GAClB,EAAE,oBAAoB,GAAG,sBAAsB,CA8C/C;AAED,6EAA6E;AAC7E,wBAAgB,uBAAuB,CAAC,EACtC,eAAe,EACf,IAAI,EACJ,iBAAsB,EACtB,iBAAiB,GAClB,EAAE,8BAA8B,GAAG,sBAAsB,CAOzD"}
|
|
@@ -25,10 +25,23 @@ function getObject(value) {
|
|
|
25
25
|
}
|
|
26
26
|
return { ...value };
|
|
27
27
|
}
|
|
28
|
-
|
|
28
|
+
function getFiniteNumber(value) {
|
|
29
|
+
return typeof value === 'number' && Number.isFinite(value) ? value : null;
|
|
30
|
+
}
|
|
31
|
+
/** Reads a valid numeric agents.max_depth value from Codex TOML content. */
|
|
32
|
+
export function readCodexMaxDepth(content) {
|
|
33
|
+
const parsed = parseConfig(content);
|
|
34
|
+
const agents = getObject(parsed.agents);
|
|
35
|
+
return getFiniteNumber(agents.max_depth);
|
|
36
|
+
}
|
|
37
|
+
/** Merges managed Codex roles and required shared agent configuration. */
|
|
38
|
+
export function mergeCodexConfig({ existingContent, desiredRoles, staleManagedRoles = [], inheritedMaxDepth, }) {
|
|
29
39
|
const parsed = parseConfig(existingContent);
|
|
30
40
|
const features = getObject(parsed.features);
|
|
31
41
|
const agents = getObject(parsed.agents);
|
|
42
|
+
const targetMaxDepth = getFiniteNumber(agents.max_depth);
|
|
43
|
+
const validInheritedMaxDepth = getFiniteNumber(inheritedMaxDepth);
|
|
44
|
+
agents.max_depth = Math.max(2, targetMaxDepth ?? 2, validInheritedMaxDepth ?? 2);
|
|
32
45
|
const nextConfig = {
|
|
33
46
|
...parsed,
|
|
34
47
|
features: {
|
|
@@ -59,10 +72,12 @@ export function mergeCodexConfig({ existingContent, desiredRoles, staleManagedRo
|
|
|
59
72
|
removedRoles,
|
|
60
73
|
};
|
|
61
74
|
}
|
|
62
|
-
|
|
75
|
+
/** Merges one managed Codex role using the shared configuration contract. */
|
|
76
|
+
export function mergeCodexConfigForRole({ existingContent, role, staleManagedRoles = [], inheritedMaxDepth, }) {
|
|
63
77
|
return mergeCodexConfig({
|
|
64
78
|
existingContent,
|
|
65
79
|
desiredRoles: [role],
|
|
66
80
|
staleManagedRoles,
|
|
81
|
+
inheritedMaxDepth,
|
|
67
82
|
});
|
|
68
83
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sync-extension.d.ts","sourceRoot":"","sources":["../../../../src/providers/codex/codec/sync-extension.ts"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"sync-extension.d.ts","sourceRoot":"","sources":["../../../../src/providers/codex/codec/sync-extension.ts"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAyBpD,MAAM,MAAM,oBAAoB,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,MAAM,CAAC;AAC3E,MAAM,MAAM,oBAAoB,GAAG,MAAM,GAAG,QAAQ,CAAC;AAErD,MAAM,WAAW,uBAAuB;IACtC,MAAM,EAAE,oBAAoB,CAAC;IAC7B,MAAM,EAAE,oBAAoB,CAAC;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,4BAA6B,SAAQ,uBAAuB;IAC3E,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,kBAAkB;IACjC,UAAU,EAAE,4BAA4B,EAAE,CAAC;IAC3C,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,mBAAmB,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,yBAAyB;IACxC,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;CACjB;AAgBD,UAAU,iCAAiC;IACzC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;CACzB;AAqiBD,wBAAsB,gCAAgC,CACpD,SAAS,EAAE,MAAM,EACjB,gBAAgB,EAAE,cAAc,EAAE,EAClC,qBAAqB,CAAC,EAAE,MAAM,EAAE,EAChC,OAAO,GAAE,iCAAsC,GAC9C,OAAO,CAAC,kBAAkB,CAAC,CAqJ7B;AAED,wBAAsB,8BAA8B,CAClD,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,kBAAkB,GACvB,OAAO,CAAC,yBAAyB,CAAC,CA6BpC;AAED,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,kBAAkB,GAAG,OAAO,CAE1E;AAED,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,kBAAkB,GAAG;IACjE,iBAAiB,EAAE,MAAM,CAAC;IAC1B,OAAO,EAAE,MAAM,CAAC;CACjB,CAaA;AAED,wBAAgB,0BAA0B,CACxC,IAAI,EAAE,kBAAkB,GACvB,uBAAuB,EAAE,CAQ3B"}
|