@open-agent-toolkit/cli 0.2.49 → 0.2.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/bundle-metadata.json +1 -1
- package/assets/docs/cli-utilities/tool-packs.md +35 -24
- package/assets/docs/reference/cli-reference.md +20 -5
- package/assets/docs/reference/file-locations.md +8 -2
- package/assets/docs/reference/oat-directory-structure.md +14 -5
- package/assets/docs/reference/troubleshooting.md +22 -4
- package/assets/docs/workflows/projects/artifacts.md +9 -4
- package/assets/docs/workflows/projects/lifecycle.md +17 -5
- package/assets/docs/workflows/projects/picking-up-projects.md +26 -9
- package/assets/docs/workflows/projects/pr-flow.md +5 -3
- package/assets/docs/workflows/projects/reviewing-oat-prs.md +12 -8
- package/assets/public-package-versions.json +4 -4
- package/assets/skills/oat-project-autonomous/references/gate-inventory.md +2 -2
- package/assets/skills/oat-project-complete/SKILL.md +193 -26
- package/assets/skills/oat-project-complete/scripts/execute-synced-archive-entry.mjs +306 -0
- package/assets/skills/oat-project-complete/scripts/finalize-synced-archive.mjs +125 -0
- package/assets/skills/oat-project-complete/scripts/parse-synced-archive-resume-fields.mjs +106 -0
- package/assets/skills/oat-project-complete/scripts/recover-completion-receipts.mjs +110 -0
- package/assets/skills/oat-project-complete/scripts/resolve-synced-archive-entry.mjs +164 -0
- package/assets/skills/oat-project-document/references/docs/autonomy-contract.md +2 -2
- package/assets/skills/oat-project-implement/references/docs/autonomy-contract.md +2 -2
- package/assets/skills/oat-project-pr-final/references/docs/autonomy-contract.md +2 -2
- package/assets/skills/oat-project-quick-start/references/docs/autonomy-contract.md +2 -2
- package/dist/commands/doctor/index.d.ts +7 -0
- package/dist/commands/doctor/index.d.ts.map +1 -1
- package/dist/commands/doctor/index.js +44 -23
- package/dist/commands/pjm/index.d.ts +0 -2
- package/dist/commands/pjm/index.d.ts.map +1 -1
- package/dist/commands/pjm/index.js +5 -4
- package/dist/commands/pjm/migrate.d.ts +2 -1
- package/dist/commands/pjm/migrate.d.ts.map +1 -1
- package/dist/commands/pjm/migrate.js +23 -17
- package/dist/commands/project/archive/archive-utils.d.ts +8 -1
- package/dist/commands/project/archive/archive-utils.d.ts.map +1 -1
- package/dist/commands/project/archive/archive-utils.js +147 -50
- package/dist/commands/project/archive/push-runner.d.ts.map +1 -1
- package/dist/commands/project/archive/push-runner.js +15 -2
- package/dist/commands/project/links/compute.d.ts +1 -0
- package/dist/commands/project/links/compute.d.ts.map +1 -1
- package/dist/commands/project/links/compute.js +5 -4
- package/dist/commands/project/links/index.d.ts +9 -0
- package/dist/commands/project/links/index.d.ts.map +1 -1
- package/dist/commands/project/links/index.js +71 -2
- package/dist/commands/project/list.d.ts +10 -2
- package/dist/commands/project/list.d.ts.map +1 -1
- package/dist/commands/project/list.js +205 -29
- package/dist/commands/project/open/index.d.ts +2 -0
- package/dist/commands/project/open/index.d.ts.map +1 -1
- package/dist/commands/project/open/index.js +16 -1
- package/dist/commands/project/prune/index.d.ts +10 -4
- package/dist/commands/project/prune/index.d.ts.map +1 -1
- package/dist/commands/project/prune/index.js +85 -15
- package/dist/commands/project/pull/index.d.ts +4 -0
- package/dist/commands/project/pull/index.d.ts.map +1 -1
- package/dist/commands/project/pull/index.js +82 -3
- package/dist/commands/project/sync/git.d.ts +9 -0
- package/dist/commands/project/sync/git.d.ts.map +1 -1
- package/dist/commands/project/sync/git.js +18 -0
- package/dist/commands/project/sync/ref-sync.d.ts +16 -1
- package/dist/commands/project/sync/ref-sync.d.ts.map +1 -1
- package/dist/commands/project/sync/ref-sync.js +288 -17
- package/dist/commands/project/sync/resolve-target.d.ts +10 -0
- package/dist/commands/project/sync/resolve-target.d.ts.map +1 -1
- package/dist/commands/project/sync/resolve-target.js +56 -1
- package/dist/commands/shared/project-scope.d.ts +2 -0
- package/dist/commands/shared/project-scope.d.ts.map +1 -1
- package/dist/commands/shared/project-scope.js +5 -0
- package/dist/commands/state/generate.d.ts +2 -0
- package/dist/commands/state/generate.d.ts.map +1 -1
- package/dist/commands/state/generate.js +93 -28
- package/dist/commands/status/index.d.ts +3 -1
- package/dist/commands/status/index.d.ts.map +1 -1
- package/dist/commands/status/index.js +77 -10
- package/dist/commands/tools/shared/pack-inventory.d.ts +10 -0
- package/dist/commands/tools/shared/pack-inventory.d.ts.map +1 -1
- package/dist/commands/tools/shared/pack-inventory.js +71 -21
- package/package.json +2 -2
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
import { execSync } from 'node:child_process';
|
|
2
2
|
import { readdir, writeFile } from 'node:fs/promises';
|
|
3
|
-
import { basename, join } from 'node:path';
|
|
3
|
+
import { basename, dirname, join, resolve } from 'node:path';
|
|
4
|
+
import { classifyLegacySyncedRecord, probeAuthoritativeCompletedRef, } from '../project/list.js';
|
|
5
|
+
import { defaultGitRunner } from '../project/sync/git.js';
|
|
6
|
+
import { listSyncedRecords } from '../project/sync/record.js';
|
|
7
|
+
import { buildSyncTarget } from '../project/sync/ref-sync.js';
|
|
8
|
+
import { probeSyncedTerminalRefs } from '../project/sync/resolve-target.js';
|
|
4
9
|
import { parseFrontmatterField } from '../shared/frontmatter.js';
|
|
5
10
|
import { resolveProjectsRoot } from '../shared/oat-paths.js';
|
|
11
|
+
import { resolveScopeRoot } from '../shared/project-scope.js';
|
|
6
12
|
import { readOatLocalConfig } from '../../config/oat-config.js';
|
|
7
13
|
import { ensureDir, fileExists } from '../../fs/io.js';
|
|
8
14
|
const defaultGit = {
|
|
@@ -310,22 +316,41 @@ function isTerminalCoordinationProject(kind, phase, phaseStatus) {
|
|
|
310
316
|
phase === 'decomposition' &&
|
|
311
317
|
phaseStatus === 'complete');
|
|
312
318
|
}
|
|
313
|
-
async function listAvailableProjects(repoRoot, projectsRoot) {
|
|
314
|
-
const
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
};
|
|
319
|
+
async function listAvailableProjects(repoRoot, projectsRoot, gitRunner) {
|
|
320
|
+
const lines = [];
|
|
321
|
+
const decompositions = [];
|
|
322
|
+
const materializedSynced = new Set();
|
|
323
|
+
for (const scope of ['shared', 'synced', 'local']) {
|
|
324
|
+
const scopeRoot = resolveScopeRoot(repoRoot, projectsRoot, scope);
|
|
325
|
+
let entries;
|
|
326
|
+
try {
|
|
327
|
+
entries = await readdir(scopeRoot, { withFileTypes: true });
|
|
323
328
|
}
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
329
|
+
catch {
|
|
330
|
+
continue;
|
|
331
|
+
}
|
|
332
|
+
for (const dir of entries.filter((entry) => entry.isDirectory())) {
|
|
333
|
+
const stateFile = join(scopeRoot, dir.name, 'state.md');
|
|
328
334
|
if (await fileExists(stateFile)) {
|
|
335
|
+
if (scope === 'synced') {
|
|
336
|
+
materializedSynced.add(dir.name);
|
|
337
|
+
const target = buildSyncTarget(repoRoot, projectsRoot, dir.name);
|
|
338
|
+
const terminal = await probeAuthoritativeCompletedRef(target, gitRunner);
|
|
339
|
+
if (terminal) {
|
|
340
|
+
const row = classifyLegacySyncedRecord({
|
|
341
|
+
schemaVersion: 1,
|
|
342
|
+
slug: dir.name,
|
|
343
|
+
scope: 'synced',
|
|
344
|
+
ref: target.ref,
|
|
345
|
+
remote: 'origin',
|
|
346
|
+
status: 'active',
|
|
347
|
+
createdAt: new Date(0).toISOString(),
|
|
348
|
+
completedAt: null,
|
|
349
|
+
}, target.projectPath, terminal);
|
|
350
|
+
lines.push(`- **${dir.name}** - ${row.recommendation.reason}`);
|
|
351
|
+
continue;
|
|
352
|
+
}
|
|
353
|
+
}
|
|
329
354
|
const phase = (await parseFrontmatterField(stateFile, 'oat_phase')) || 'unknown';
|
|
330
355
|
const phaseStatus = (await parseFrontmatterField(stateFile, 'oat_phase_status')) ||
|
|
331
356
|
'in_progress';
|
|
@@ -340,19 +365,29 @@ async function listAvailableProjects(repoRoot, projectsRoot) {
|
|
|
340
365
|
}
|
|
341
366
|
}
|
|
342
367
|
}
|
|
343
|
-
return {
|
|
344
|
-
active: lines.length > 0 ? lines.join('\n') : '*(No projects found)*',
|
|
345
|
-
decompositions: decompositions.length > 0
|
|
346
|
-
? decompositions.join('\n')
|
|
347
|
-
: '*(No decompositions found)*',
|
|
348
|
-
};
|
|
349
368
|
}
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
369
|
+
const syncedRoot = resolveScopeRoot(repoRoot, projectsRoot, 'synced');
|
|
370
|
+
const records = await listSyncedRecords(syncedRoot);
|
|
371
|
+
for (const record of records) {
|
|
372
|
+
if (materializedSynced.has(record.slug))
|
|
373
|
+
continue;
|
|
374
|
+
const target = buildSyncTarget(repoRoot, projectsRoot, record.slug);
|
|
375
|
+
const authoritative = await probeAuthoritativeCompletedRef(target, gitRunner);
|
|
376
|
+
const probe = authoritative ??
|
|
377
|
+
(record.archiveSourceRefSha
|
|
378
|
+
? await probeSyncedTerminalRefs(target, record.archiveSourceRefSha, gitRunner)
|
|
379
|
+
: undefined);
|
|
380
|
+
const row = classifyLegacySyncedRecord(record, target.projectPath, probe);
|
|
381
|
+
lines.push(row.kind === 'recorded-absent'
|
|
382
|
+
? `- **${record.slug}** - checkout absent; oat project pull ${record.slug}`
|
|
383
|
+
: `- **${record.slug}** - ${row.recommendation.reason}`);
|
|
355
384
|
}
|
|
385
|
+
return {
|
|
386
|
+
active: lines.length > 0 ? lines.join('\n') : '*(No projects found)*',
|
|
387
|
+
decompositions: decompositions.length > 0
|
|
388
|
+
? decompositions.join('\n')
|
|
389
|
+
: '*(No decompositions found)*',
|
|
390
|
+
};
|
|
356
391
|
}
|
|
357
392
|
function buildDashboardMarkdown(project, state, knowledge, staleness, nextStep, projectsList, generatedDate) {
|
|
358
393
|
const timestamp = `${generatedDate}`;
|
|
@@ -453,18 +488,48 @@ export async function generateStateDashboard(options) {
|
|
|
453
488
|
const env = options.env ?? process.env;
|
|
454
489
|
const today = options.today ?? new Date().toISOString().slice(0, 10);
|
|
455
490
|
const git = options.git ?? defaultGit;
|
|
491
|
+
const gitRunner = options.gitRunner ?? defaultGitRunner;
|
|
456
492
|
const dashboardPath = join(repoRoot, '.oat', 'state.md');
|
|
457
493
|
const projectsRoot = await resolveProjectsRoot(repoRoot, env);
|
|
458
494
|
const hasProjects = await hasAnyProjects(join(repoRoot, projectsRoot));
|
|
459
495
|
const project = await readActiveProject(repoRoot);
|
|
496
|
+
let terminalNextStep = null;
|
|
497
|
+
if (project.status === 'active' && project.path) {
|
|
498
|
+
const activePath = resolve(repoRoot, project.path);
|
|
499
|
+
const syncedRoot = resolveScopeRoot(repoRoot, projectsRoot, 'synced');
|
|
500
|
+
if (dirname(activePath) === syncedRoot) {
|
|
501
|
+
const target = buildSyncTarget(repoRoot, projectsRoot, project.name);
|
|
502
|
+
const terminal = await probeAuthoritativeCompletedRef(target, gitRunner);
|
|
503
|
+
if (terminal) {
|
|
504
|
+
const row = classifyLegacySyncedRecord({
|
|
505
|
+
schemaVersion: 1,
|
|
506
|
+
slug: project.name,
|
|
507
|
+
scope: 'synced',
|
|
508
|
+
ref: target.ref,
|
|
509
|
+
remote: 'origin',
|
|
510
|
+
status: 'active',
|
|
511
|
+
createdAt: new Date(0).toISOString(),
|
|
512
|
+
completedAt: null,
|
|
513
|
+
}, activePath, terminal);
|
|
514
|
+
project.status =
|
|
515
|
+
row.kind === 'terminal-invalid'
|
|
516
|
+
? 'terminal ref mismatch'
|
|
517
|
+
: 'terminal cleanup pending';
|
|
518
|
+
terminalNextStep = {
|
|
519
|
+
step: 'oat-project-complete',
|
|
520
|
+
reason: row.recommendation.reason,
|
|
521
|
+
};
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
}
|
|
460
525
|
let state = null;
|
|
461
526
|
if (project.status === 'active') {
|
|
462
527
|
state = await readProjectState(repoRoot, project.path);
|
|
463
528
|
}
|
|
464
529
|
const knowledge = await readKnowledgeStatus(repoRoot);
|
|
465
530
|
const staleness = calculateStaleness(knowledge, git, repoRoot, today);
|
|
466
|
-
const nextStep = computeNextStep(project, hasProjects, state);
|
|
467
|
-
const projectsList = await listAvailableProjects(repoRoot, projectsRoot);
|
|
531
|
+
const nextStep = terminalNextStep ?? computeNextStep(project, hasProjects, state);
|
|
532
|
+
const projectsList = await listAvailableProjects(repoRoot, projectsRoot, gitRunner);
|
|
468
533
|
const markdown = buildDashboardMarkdown(project, state, knowledge, staleness, nextStep, projectsList, today);
|
|
469
534
|
await ensureDir(join(repoRoot, '.oat'));
|
|
470
535
|
await writeFile(dashboardPath, markdown, 'utf8');
|
|
@@ -24,7 +24,9 @@ interface StatusDependencies {
|
|
|
24
24
|
scanCanonical: (scopeRoot: string, scope: ConcreteScope) => Promise<CanonicalEntry[]>;
|
|
25
25
|
scanBundledManagedAgents: () => Promise<CanonicalEntry[]>;
|
|
26
26
|
getAdapters: () => ProviderAdapter[];
|
|
27
|
-
|
|
27
|
+
getConfigAwareAdapters: (adapters: ProviderAdapter[], scopeRoot: string, config: SyncConfig) => Promise<{
|
|
28
|
+
activeAdapters: ProviderAdapter[];
|
|
29
|
+
}>;
|
|
28
30
|
getSyncMappings: (adapter: ProviderAdapter, scope: Scope) => PathMapping[];
|
|
29
31
|
getAdoptionSources: (adapter: ProviderAdapter, scope: Scope) => AdoptionSource[];
|
|
30
32
|
detectDrift: (entry: Manifest['entries'][number], scopeRoot: string, copyTransform?: CopyTransform) => Promise<DriftReport>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/status/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAEL,KAAK,cAAc,EACnB,KAAK,aAAa,EACnB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAEL,KAAK,WAAW,EAChB,KAAK,yBAAyB,EAC/B,MAAM,wBAAwB,CAAC;AAMhC,OAAO,EACL,KAAK,cAAc,EAIpB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAIL,KAAK,sBAAsB,EAC5B,MAAM,2CAA2C,CAAC;AAEnD,OAAO,EAEL,KAAK,iBAAiB,EACtB,KAAK,aAAa,EAClB,KAAK,YAAY,EAGlB,MAAM,iCAAiC,CAAC;AAKzC,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/status/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -7,7 +7,7 @@ import { applyNativeSkillDisposition, getNativeSkillProviderDetails, isNativeSki
|
|
|
7
7
|
import { withScopeOption } from '../shared/scope-option.js';
|
|
8
8
|
import { confirmAction, selectManyWithAbort, selectWithAbort, } from '../shared/shared.prompts.js';
|
|
9
9
|
import { readGlobalOptions, resolveConcreteScopes, } from '../shared/shared.utils.js';
|
|
10
|
-
import { hasScopedPackPlacementEvidence, inventoryPack, } from '../tools/shared/pack-inventory.js';
|
|
10
|
+
import { attributeSharedOwnerDiagnostics, hasScopedPackPlacementEvidence, inventoryPack, } from '../tools/shared/pack-inventory.js';
|
|
11
11
|
import { PACK_NAMES } from '../tools/shared/pack-manifest.js';
|
|
12
12
|
import { formatPackPath, formatPackPaths, updatePackRecovery, } from '../tools/shared/pack-paths.js';
|
|
13
13
|
import { DEFAULT_SYNC_CONFIG, loadSyncConfig, } from '../../config/index.js';
|
|
@@ -24,12 +24,45 @@ import { copilotAdapter } from '../../providers/copilot/index.js';
|
|
|
24
24
|
import { cursorAdapter } from '../../providers/cursor/index.js';
|
|
25
25
|
import { applyCursorProjectExtensionPlan, computeCursorProjectExtensionPlan, } from '../../providers/cursor/codec/sync-extension.js';
|
|
26
26
|
import { geminiAdapter } from '../../providers/gemini/index.js';
|
|
27
|
-
import {
|
|
27
|
+
import { getConfigAwareAdapters, getSyncMappings, } from '../../providers/shared/index.js';
|
|
28
28
|
import { getAdoptionSources } from '../../providers/shared/adapter.utils.js';
|
|
29
29
|
import { SCOPE_CONTENT_TYPES, } from '../../shared/types.js';
|
|
30
30
|
import { formatStatusTable } from '../../ui/output.js';
|
|
31
31
|
import { Command } from 'commander';
|
|
32
32
|
const DEFAULT_REMEDIATION = 'Run "oat init" to adopt stray entries.';
|
|
33
|
+
function unavailablePackReport(error, roots, unavailableScopes) {
|
|
34
|
+
let detail = error instanceof Error ? error.message : 'Unknown error.';
|
|
35
|
+
const replacements = [
|
|
36
|
+
...(roots.projectRoot
|
|
37
|
+
? [
|
|
38
|
+
[`${roots.projectRoot}/`, ''],
|
|
39
|
+
[roots.projectRoot, '.'],
|
|
40
|
+
]
|
|
41
|
+
: []),
|
|
42
|
+
...(roots.userRoot
|
|
43
|
+
? [
|
|
44
|
+
[`${roots.userRoot}/`, '~/'],
|
|
45
|
+
[roots.userRoot, '~'],
|
|
46
|
+
]
|
|
47
|
+
: []),
|
|
48
|
+
].sort(([left], [right]) => right.length - left.length);
|
|
49
|
+
for (const [root, replacement] of replacements) {
|
|
50
|
+
detail = detail.replaceAll(root, replacement);
|
|
51
|
+
}
|
|
52
|
+
return {
|
|
53
|
+
availability: {
|
|
54
|
+
status: 'unavailable',
|
|
55
|
+
diagnostic: {
|
|
56
|
+
code: 'packs:inventory',
|
|
57
|
+
message: `Unable to inventory managed packs: ${detail}`,
|
|
58
|
+
recovery: 'Run `pnpm build` and rerun `oat status`.',
|
|
59
|
+
},
|
|
60
|
+
},
|
|
61
|
+
states: [],
|
|
62
|
+
unavailableScopes,
|
|
63
|
+
pjm: null,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
33
66
|
const DEFAULT_DEPENDENCIES = {
|
|
34
67
|
buildCommandContext,
|
|
35
68
|
async resolveScopeRoot(scope, context) {
|
|
@@ -55,7 +88,7 @@ const DEFAULT_DEPENDENCIES = {
|
|
|
55
88
|
geminiAdapter,
|
|
56
89
|
];
|
|
57
90
|
},
|
|
58
|
-
|
|
91
|
+
getConfigAwareAdapters,
|
|
59
92
|
getSyncMappings,
|
|
60
93
|
getAdoptionSources,
|
|
61
94
|
detectDrift,
|
|
@@ -210,7 +243,7 @@ function shouldReportPjmAdoption(adoption, states) {
|
|
|
210
243
|
const pjm = states.find(({ pack }) => pack === 'project-management');
|
|
211
244
|
return (pjm?.scopes ?? []).some(({ scope }) => scope === 'project');
|
|
212
245
|
}
|
|
213
|
-
async function collectPackReport(scopeRoots, unavailableScopes, dependencies) {
|
|
246
|
+
async function collectPackReport(scopeRoots, unavailableScopes, userManagedRoleMaterialization, dependencies) {
|
|
214
247
|
const roots = {
|
|
215
248
|
...(scopeRoots.has('project')
|
|
216
249
|
? { projectRoot: scopeRoots.get('project') }
|
|
@@ -218,22 +251,46 @@ async function collectPackReport(scopeRoots, unavailableScopes, dependencies) {
|
|
|
218
251
|
...(scopeRoots.has('user') ? { userRoot: scopeRoots.get('user') } : {}),
|
|
219
252
|
};
|
|
220
253
|
if (scopeRoots.size === 0) {
|
|
221
|
-
return {
|
|
254
|
+
return {
|
|
255
|
+
availability: { status: 'available' },
|
|
256
|
+
states: [],
|
|
257
|
+
unavailableScopes,
|
|
258
|
+
pjm: null,
|
|
259
|
+
};
|
|
260
|
+
}
|
|
261
|
+
let inventories;
|
|
262
|
+
try {
|
|
263
|
+
const assetsRoot = await dependencies.resolveAssetsRoot();
|
|
264
|
+
inventories = attributeSharedOwnerDiagnostics(await Promise.all(PACK_NAMES.map((pack) => dependencies.inventoryPack({
|
|
265
|
+
pack,
|
|
266
|
+
assetsRoot,
|
|
267
|
+
...roots,
|
|
268
|
+
...(scopeRoots.has('user')
|
|
269
|
+
? { userManagedRoleMaterialization }
|
|
270
|
+
: {}),
|
|
271
|
+
}))));
|
|
272
|
+
}
|
|
273
|
+
catch (error) {
|
|
274
|
+
return unavailablePackReport(error, roots, unavailableScopes);
|
|
222
275
|
}
|
|
223
|
-
const assetsRoot = await dependencies.resolveAssetsRoot();
|
|
224
|
-
const inventories = await Promise.all(PACK_NAMES.map((pack) => dependencies.inventoryPack({ pack, assetsRoot, ...roots })));
|
|
225
276
|
const states = inventories
|
|
226
277
|
.map((inventory) => toStatusPackState(inventory, roots))
|
|
227
278
|
.filter((state) => state !== null);
|
|
228
279
|
const projectRoot = scopeRoots.get('project');
|
|
229
280
|
if (!projectRoot) {
|
|
230
|
-
return {
|
|
281
|
+
return {
|
|
282
|
+
availability: { status: 'available' },
|
|
283
|
+
states,
|
|
284
|
+
unavailableScopes,
|
|
285
|
+
pjm: null,
|
|
286
|
+
};
|
|
231
287
|
}
|
|
232
288
|
const adoption = await dependencies.resolvePjmAdoption({
|
|
233
289
|
projectRoot,
|
|
234
290
|
repoRoot: join(projectRoot, '.oat', 'repo'),
|
|
235
291
|
});
|
|
236
292
|
return {
|
|
293
|
+
availability: { status: 'available' },
|
|
237
294
|
states,
|
|
238
295
|
unavailableScopes,
|
|
239
296
|
pjm: {
|
|
@@ -262,6 +319,9 @@ function describePackScope(state) {
|
|
|
262
319
|
}
|
|
263
320
|
function formatPackReport(report) {
|
|
264
321
|
const lines = [];
|
|
322
|
+
if (report.availability.diagnostic) {
|
|
323
|
+
lines.push(`${report.availability.diagnostic.code}: ${report.availability.diagnostic.message}`, ` Fix: ${report.availability.diagnostic.recovery}`);
|
|
324
|
+
}
|
|
265
325
|
if (report.states.length > 0) {
|
|
266
326
|
lines.push('Pack state:');
|
|
267
327
|
for (const state of report.states) {
|
|
@@ -275,6 +335,9 @@ function formatPackReport(report) {
|
|
|
275
335
|
}
|
|
276
336
|
for (const diagnostic of scope.diagnostics) {
|
|
277
337
|
lines.push(` ${diagnostic.code}: ${diagnostic.message}`);
|
|
338
|
+
if (diagnostic.paths.length > 0) {
|
|
339
|
+
lines.push(` Affected: ${formatPackPaths(diagnostic.paths, {})}`);
|
|
340
|
+
}
|
|
278
341
|
if (diagnostic.recovery) {
|
|
279
342
|
lines.push(` Fix: ${diagnostic.recovery}`);
|
|
280
343
|
}
|
|
@@ -285,6 +348,9 @@ function formatPackReport(report) {
|
|
|
285
348
|
}
|
|
286
349
|
for (const diagnostic of state.diagnostics) {
|
|
287
350
|
lines.push(` ${diagnostic.code}: ${diagnostic.message}`);
|
|
351
|
+
if (diagnostic.paths.length > 0) {
|
|
352
|
+
lines.push(` Affected: ${formatPackPaths(diagnostic.paths, {})}`);
|
|
353
|
+
}
|
|
288
354
|
if (diagnostic.recovery) {
|
|
289
355
|
lines.push(` Fix: ${diagnostic.recovery}`);
|
|
290
356
|
}
|
|
@@ -316,7 +382,7 @@ async function collectScopeReports(scope, context, dependencies) {
|
|
|
316
382
|
dependencies.resolveUserSyncConfig(userConfigDir),
|
|
317
383
|
]);
|
|
318
384
|
const adapters = dependencies.getAdapters();
|
|
319
|
-
const activeAdapters = await dependencies.
|
|
385
|
+
const { activeAdapters } = await dependencies.getConfigAwareAdapters(adapters, scopeRoot, scope === 'user' ? userSyncConfig : syncConfig);
|
|
320
386
|
const reports = [];
|
|
321
387
|
const strayCandidates = [];
|
|
322
388
|
const trackedCanonicalByProvider = new Set(manifest.entries.map((entry) => `${entry.provider}|${normalizeToPosixPath(entry.canonicalPath)}`));
|
|
@@ -526,7 +592,8 @@ async function runStatusCommand(context, dependencies, options = {}) {
|
|
|
526
592
|
}
|
|
527
593
|
return;
|
|
528
594
|
}
|
|
529
|
-
const packReport = await collectPackReport(scopeRoots, unavailableScopes,
|
|
595
|
+
const packReport = await collectPackReport(scopeRoots, unavailableScopes, scopeCollections.some(({ scope, activeAdapterNames }) => scope === 'user' &&
|
|
596
|
+
activeAdapterNames.some((name) => name === 'codex' || name === 'cursor')), dependencies);
|
|
530
597
|
if (context.json) {
|
|
531
598
|
const payload = {
|
|
532
599
|
scope: context.scope,
|
|
@@ -33,14 +33,24 @@ export interface InventoryScopedPackInput {
|
|
|
33
33
|
scope: ConcreteScope;
|
|
34
34
|
scopeRoot: string;
|
|
35
35
|
assetsRoot: string;
|
|
36
|
+
managedRoleMaterialization?: boolean;
|
|
36
37
|
}
|
|
37
38
|
export interface InventoryPackInput {
|
|
38
39
|
pack: PackName;
|
|
39
40
|
assetsRoot: string;
|
|
40
41
|
projectRoot?: string;
|
|
41
42
|
userRoot?: string;
|
|
43
|
+
userManagedRoleMaterialization?: boolean;
|
|
42
44
|
}
|
|
43
45
|
export declare function inventoryScopedPack(input: InventoryScopedPackInput): Promise<ScopedPackInventory>;
|
|
44
46
|
export declare function hasScopedPackPlacementEvidence(inventory: ScopedPackInventory): boolean;
|
|
47
|
+
/**
|
|
48
|
+
* Attribute each present shared asset only after every candidate pack has been
|
|
49
|
+
* inventoried. Shared presence cannot establish placement, so applicable
|
|
50
|
+
* owners are limited to packs with independent intent or non-shared managed
|
|
51
|
+
* assets. The observation is attached once to the first applicable owner in
|
|
52
|
+
* canonical pack order while naming the complete applicable owner set.
|
|
53
|
+
*/
|
|
54
|
+
export declare function attributeSharedOwnerDiagnostics(inventories: PackInventory[]): PackInventory[];
|
|
45
55
|
export declare function inventoryPack(input: InventoryPackInput): Promise<PackInventory>;
|
|
46
56
|
//# sourceMappingURL=pack-inventory.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pack-inventory.d.ts","sourceRoot":"","sources":["../../../../src/commands/tools/shared/pack-inventory.ts"],"names":[],"mappings":"AAaA,OAAO,EACL,KAAK,aAAa,EAEnB,MAAM,eAAe,CAAC;AAIvB,OAAO,EAEL,KAAK,gBAAgB,EAEtB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,KAAK,EACV,mBAAmB,EACnB,eAAe,EACf,gBAAgB,EAChB,QAAQ,EACT,MAAM,SAAS,CAAC;AAEjB,MAAM,WAAW,kBAAkB;IACjC,UAAU,EAAE,mBAAmB,CAAC;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,eAAe,CAAC;IACxB,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/B;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EACA,uBAAuB,GACvB,iBAAiB,GACjB,0BAA0B,GAC1B,2BAA2B,CAAC;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,QAAQ,CAAC,EAAE,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;CACjC;AAED,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,QAAQ,CAAC;IACf,KAAK,EAAE,aAAa,CAAC;IACrB,MAAM,EAAE,gBAAgB,CAAC;IACzB,YAAY,EAAE,gBAAgB,CAAC;IAC/B,MAAM,EAAE,kBAAkB,EAAE,CAAC;IAC7B,WAAW,EAAE,cAAc,EAAE,CAAC;CAC/B;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,QAAQ,CAAC;IACf,SAAS,EAAE,SAAS,GAAG,MAAM,GAAG,MAAM,GAAG,aAAa,CAAC;IACvD,MAAM,EAAE,mBAAmB,EAAE,CAAC;IAC9B,WAAW,EAAE,cAAc,EAAE,CAAC;CAC/B;AAED,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,QAAQ,CAAC;IACf,KAAK,EAAE,aAAa,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"pack-inventory.d.ts","sourceRoot":"","sources":["../../../../src/commands/tools/shared/pack-inventory.ts"],"names":[],"mappings":"AAaA,OAAO,EACL,KAAK,aAAa,EAEnB,MAAM,eAAe,CAAC;AAIvB,OAAO,EAEL,KAAK,gBAAgB,EAEtB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,KAAK,EACV,mBAAmB,EACnB,eAAe,EACf,gBAAgB,EAChB,QAAQ,EACT,MAAM,SAAS,CAAC;AAEjB,MAAM,WAAW,kBAAkB;IACjC,UAAU,EAAE,mBAAmB,CAAC;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,eAAe,CAAC;IACxB,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/B;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EACA,uBAAuB,GACvB,iBAAiB,GACjB,0BAA0B,GAC1B,2BAA2B,CAAC;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,QAAQ,CAAC,EAAE,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;CACjC;AAED,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,QAAQ,CAAC;IACf,KAAK,EAAE,aAAa,CAAC;IACrB,MAAM,EAAE,gBAAgB,CAAC;IACzB,YAAY,EAAE,gBAAgB,CAAC;IAC/B,MAAM,EAAE,kBAAkB,EAAE,CAAC;IAC7B,WAAW,EAAE,cAAc,EAAE,CAAC;CAC/B;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,QAAQ,CAAC;IACf,SAAS,EAAE,SAAS,GAAG,MAAM,GAAG,MAAM,GAAG,aAAa,CAAC;IACvD,MAAM,EAAE,mBAAmB,EAAE,CAAC;IAC9B,WAAW,EAAE,cAAc,EAAE,CAAC;CAC/B;AAED,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,QAAQ,CAAC;IACf,KAAK,EAAE,aAAa,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,0BAA0B,CAAC,EAAE,OAAO,CAAC;CACtC;AAED,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,QAAQ,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,8BAA8B,CAAC,EAAE,OAAO,CAAC;CAC1C;AAiRD,wBAAsB,mBAAmB,CACvC,KAAK,EAAE,wBAAwB,GAC9B,OAAO,CAAC,mBAAmB,CAAC,CAwC9B;AAED,wBAAgB,8BAA8B,CAC5C,SAAS,EAAE,mBAAmB,GAC7B,OAAO,CAUT;AAED;;;;;;GAMG;AACH,wBAAgB,+BAA+B,CAC7C,WAAW,EAAE,aAAa,EAAE,GAC3B,aAAa,EAAE,CAgEjB;AAED,wBAAsB,aAAa,CACjC,KAAK,EAAE,kBAAkB,GACxB,OAAO,CAAC,aAAa,CAAC,CAiDxB"}
|
|
@@ -6,7 +6,7 @@ import { readOatConfig } from '../../../config/oat-config.js';
|
|
|
6
6
|
import { resolveManagedScopeRoots, validateManagedPath, validateRealPathWithinScope, } from '../../../fs/paths.js';
|
|
7
7
|
import { USER_SCOPE_MANAGED_AGENT_FILES, } from '../../../shared/types.js';
|
|
8
8
|
import { digestDirectory, digestFile } from './content-digest.js';
|
|
9
|
-
import { getPackDefinition } from './pack-manifest.js';
|
|
9
|
+
import { getPackDefinition, PACK_NAMES } from './pack-manifest.js';
|
|
10
10
|
import { readScopedPackIntent, } from './scoped-pack-intent.js';
|
|
11
11
|
async function pathExists(path) {
|
|
12
12
|
try {
|
|
@@ -172,27 +172,29 @@ function intentDiagnostic(diagnostic) {
|
|
|
172
172
|
return { ...diagnostic };
|
|
173
173
|
}
|
|
174
174
|
/**
|
|
175
|
-
* User-scope canonical agents are installed into `~/.agents/agents
|
|
176
|
-
* provider
|
|
177
|
-
*
|
|
178
|
-
* managed role file set (`USER_SCOPE_MANAGED_AGENT_FILES`)
|
|
179
|
-
*
|
|
180
|
-
*
|
|
175
|
+
* User-scope canonical agents are installed into `~/.agents/agents/`, while
|
|
176
|
+
* native provider-role materialization is caller-resolved from the active
|
|
177
|
+
* config-aware adapter set. When that capability is active, only the bundled
|
|
178
|
+
* managed role file set (`USER_SCOPE_MANAGED_AGENT_FILES`) is supplied to the
|
|
179
|
+
* extension. Completeness alone therefore cannot describe native
|
|
180
|
+
* materialization, so the remaining gap is named here instead of staying
|
|
181
|
+
* silent. Canonical instruction-read availability is a separate contract.
|
|
181
182
|
*/
|
|
182
|
-
function userAgentMaterializationDiagnostics(pack, scope, assets) {
|
|
183
|
+
function userAgentMaterializationDiagnostics(pack, scope, assets, managedRoleMaterialization) {
|
|
183
184
|
if (scope !== 'user')
|
|
184
185
|
return [];
|
|
185
186
|
const bundledRoleFiles = new Set(USER_SCOPE_MANAGED_AGENT_FILES);
|
|
186
187
|
const unmaterialized = assets.filter(({ definition, status }) => definition.kind === 'agent' &&
|
|
187
188
|
definition.ownership.user === 'managed' &&
|
|
188
189
|
status !== 'missing' &&
|
|
189
|
-
!
|
|
190
|
+
(!managedRoleMaterialization ||
|
|
191
|
+
!bundledRoleFiles.has(definition.destination.split('/').at(-1) ?? '')));
|
|
190
192
|
if (unmaterialized.length === 0)
|
|
191
193
|
return [];
|
|
192
194
|
return [
|
|
193
195
|
{
|
|
194
196
|
code: 'user-agent-unmaterialized',
|
|
195
|
-
message: `Pack ${pack} installs user-scope canonical agents
|
|
197
|
+
message: `Pack ${pack} installs user-scope canonical agents without native provider-role materialization for the active provider set; canonical instruction reads are unaffected. Active Codex or Cursor materialization supplies only the bundled managed role files (${USER_SCOPE_MANAGED_AGENT_FILES.join(', ')}). Install this pack at project scope to materialize the affected agents.`,
|
|
196
198
|
paths: unmaterialized.map(({ path }) => path),
|
|
197
199
|
},
|
|
198
200
|
];
|
|
@@ -210,7 +212,7 @@ export async function inventoryScopedPack(input) {
|
|
|
210
212
|
]);
|
|
211
213
|
const diagnostics = [
|
|
212
214
|
...intent.diagnostics.map(intentDiagnostic),
|
|
213
|
-
...userAgentMaterializationDiagnostics(input.pack, input.scope, assets),
|
|
215
|
+
...userAgentMaterializationDiagnostics(input.pack, input.scope, assets, input.managedRoleMaterialization ?? false),
|
|
214
216
|
];
|
|
215
217
|
return {
|
|
216
218
|
pack: input.pack,
|
|
@@ -227,6 +229,61 @@ export function hasScopedPackPlacementEvidence(inventory) {
|
|
|
227
229
|
definition.ownership[inventory.scope] === 'managed' &&
|
|
228
230
|
status !== 'missing'));
|
|
229
231
|
}
|
|
232
|
+
/**
|
|
233
|
+
* Attribute each present shared asset only after every candidate pack has been
|
|
234
|
+
* inventoried. Shared presence cannot establish placement, so applicable
|
|
235
|
+
* owners are limited to packs with independent intent or non-shared managed
|
|
236
|
+
* assets. The observation is attached once to the first applicable owner in
|
|
237
|
+
* canonical pack order while naming the complete applicable owner set.
|
|
238
|
+
*/
|
|
239
|
+
export function attributeSharedOwnerDiagnostics(inventories) {
|
|
240
|
+
const attributed = inventories.map((inventory) => ({
|
|
241
|
+
...inventory,
|
|
242
|
+
scopes: inventory.scopes.map((scoped) => ({
|
|
243
|
+
...scoped,
|
|
244
|
+
diagnostics: scoped.diagnostics.filter(({ code }) => code !== 'shared-owner-observation'),
|
|
245
|
+
})),
|
|
246
|
+
diagnostics: inventory.diagnostics.filter(({ code }) => code !== 'shared-owner-observation'),
|
|
247
|
+
}));
|
|
248
|
+
const groups = new Map();
|
|
249
|
+
for (const inventory of attributed) {
|
|
250
|
+
for (const scoped of inventory.scopes) {
|
|
251
|
+
for (const asset of scoped.assets) {
|
|
252
|
+
const owner = asset.definition.sharedOwner;
|
|
253
|
+
if (!owner || asset.status === 'missing')
|
|
254
|
+
continue;
|
|
255
|
+
const key = `${scoped.scope}:${owner}:${asset.definition.destination}`;
|
|
256
|
+
const group = groups.get(key) ?? {
|
|
257
|
+
owner,
|
|
258
|
+
destination: asset.definition.destination,
|
|
259
|
+
scope: scoped.scope,
|
|
260
|
+
candidates: [],
|
|
261
|
+
paths: new Set(),
|
|
262
|
+
};
|
|
263
|
+
group.candidates.push({ pack: inventory.pack, scoped });
|
|
264
|
+
group.paths.add(asset.path);
|
|
265
|
+
groups.set(key, group);
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
const packOrder = new Map(PACK_NAMES.map((pack, index) => [pack, index]));
|
|
270
|
+
for (const group of groups.values()) {
|
|
271
|
+
const applicable = group.candidates
|
|
272
|
+
.filter(({ scoped }) => hasScopedPackPlacementEvidence(scoped))
|
|
273
|
+
.sort((left, right) => packOrder.get(left.pack) - packOrder.get(right.pack));
|
|
274
|
+
if (applicable.length === 0)
|
|
275
|
+
continue;
|
|
276
|
+
const applicableOwners = applicable.map(({ pack }) => pack);
|
|
277
|
+
const diagnostic = {
|
|
278
|
+
code: 'shared-owner-observation',
|
|
279
|
+
message: `Shared managed asset ${group.destination} (${group.owner}) at ${group.scope} scope applies to installed or intended pack owner(s): ${applicableOwners.join(', ')}`,
|
|
280
|
+
paths: [...group.paths].sort(),
|
|
281
|
+
};
|
|
282
|
+
const selected = applicable[0];
|
|
283
|
+
selected.scoped.diagnostics.push(diagnostic);
|
|
284
|
+
}
|
|
285
|
+
return attributed;
|
|
286
|
+
}
|
|
230
287
|
export async function inventoryPack(input) {
|
|
231
288
|
const definition = getPackDefinition(input.pack);
|
|
232
289
|
const roots = {
|
|
@@ -242,6 +299,9 @@ export async function inventoryPack(input) {
|
|
|
242
299
|
scope,
|
|
243
300
|
scopeRoot,
|
|
244
301
|
assetsRoot: input.assetsRoot,
|
|
302
|
+
managedRoleMaterialization: scope === 'user'
|
|
303
|
+
? (input.userManagedRoleMaterialization ?? false)
|
|
304
|
+
: false,
|
|
245
305
|
}),
|
|
246
306
|
]
|
|
247
307
|
: [];
|
|
@@ -255,16 +315,6 @@ export async function inventoryPack(input) {
|
|
|
255
315
|
? 'user'
|
|
256
316
|
: 'unavailable';
|
|
257
317
|
const diagnostics = scopes.flatMap(({ diagnostics: values }) => values);
|
|
258
|
-
for (const scoped of scopes) {
|
|
259
|
-
const shared = scoped.assets.filter(({ definition: asset, status }) => asset.sharedOwner !== undefined && status !== 'missing');
|
|
260
|
-
if (shared.length > 0 && !hasScopedPackPlacementEvidence(scoped)) {
|
|
261
|
-
diagnostics.push({
|
|
262
|
-
code: 'shared-owner-observation',
|
|
263
|
-
message: `Pack ${input.pack} has shared managed assets at ${scoped.scope} scope without pack ownership evidence`,
|
|
264
|
-
paths: shared.map(({ path }) => path),
|
|
265
|
-
});
|
|
266
|
-
}
|
|
267
|
-
}
|
|
268
318
|
if (placement === 'both') {
|
|
269
319
|
const assets = active.flatMap(({ assets: values }) => values.filter(({ status }) => status !== 'missing'));
|
|
270
320
|
diagnostics.push({
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@open-agent-toolkit/cli",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.51",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Open Agent Toolkit CLI",
|
|
6
6
|
"homepage": "https://github.com/voxmedia/open-agent-toolkit/tree/main/packages/cli",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"ora": "^9.0.0",
|
|
35
35
|
"yaml": "2.8.2",
|
|
36
36
|
"zod": "^3.25.76",
|
|
37
|
-
"@open-agent-toolkit/control-plane": "0.2.
|
|
37
|
+
"@open-agent-toolkit/control-plane": "0.2.51"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
40
|
"@types/node": "^22.10.0",
|