@open-agent-toolkit/cli 0.0.35 → 0.0.36
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/docs/cli-utilities/tool-packs.md +5 -1
- package/assets/public-package-versions.json +4 -4
- package/dist/commands/init/tools/index.d.ts +13 -2
- package/dist/commands/init/tools/index.d.ts.map +1 -1
- package/dist/commands/init/tools/index.js +318 -82
- package/dist/commands/init/tools/install-state.d.ts +10 -0
- package/dist/commands/init/tools/install-state.d.ts.map +1 -0
- package/dist/commands/init/tools/install-state.js +36 -0
- package/dist/commands/tools/install/index.d.ts +2 -1
- package/dist/commands/tools/install/index.d.ts.map +1 -1
- package/dist/commands/tools/install/index.js +11 -5
- package/package.json +2 -2
|
@@ -73,10 +73,14 @@ Key behavior:
|
|
|
73
73
|
|
|
74
74
|
- Same pack selection and install flow as `oat init tools`
|
|
75
75
|
- Pack-oriented install subcommands: `core`, `docs`, `ideas`, `workflows`, `utility`, `project-management`, `research`
|
|
76
|
+
- Interactive installs show each pack's current install location in the picker so already-installed packs are visible before you submit
|
|
77
|
+
- User-scope follow-up choices are prepopulated from the current install state for user-eligible packs (`ideas`, `docs`, `utility`, `research`)
|
|
78
|
+
- If a user-eligible pack is already installed in both project and user scope, the installer asks whether to keep both installs or normalize the pack to user scope before it makes any cleanup changes
|
|
79
|
+
- Changing a user-eligible pack from project scope to user scope, or back again, is treated as a migration: the old canonical copy is removed so the pack ends in the selected scope instead of accumulating duplicate installs
|
|
76
80
|
- Tracks installed vs bundled skill versions and reports outdated skills
|
|
77
81
|
- Records installed pack state in shared repo config as `tools.<pack>: true` so other OAT workflows can detect installed capabilities without relying on filesystem heuristics
|
|
78
82
|
- Interactive runs can prompt to update selected outdated skills
|
|
79
|
-
-
|
|
83
|
+
- Successful installs report the final scope chosen for each pack, including `project + user` when both installs are preserved, and auto-sync every scope touched by the install or migration
|
|
80
84
|
- Install-triggered auto-sync limits removal planning to the canonical entries from the pack that was just installed, so stale manifest drift in unrelated packs does not delete other provider views
|
|
81
85
|
- Use `--no-sync` to skip auto-sync
|
|
82
86
|
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import { type CommandContext, type GlobalOptions } from '../../../app/command-context.js';
|
|
2
2
|
import { type UpsertSectionResult } from '../../shared/agents-md.js';
|
|
3
3
|
import { type MultiSelectChoice, type PromptContext, type SelectChoice } from '../../shared/shared.prompts.js';
|
|
4
|
+
import type { ScanToolsOptions } from '../../tools/shared/scan-tools.js';
|
|
5
|
+
import type { ToolInfo } from '../../tools/shared/types.js';
|
|
4
6
|
import { type OatConfig } from '../../../config/oat-config.js';
|
|
7
|
+
import type { ConcreteScope } from '../../../shared/types.js';
|
|
5
8
|
import { Command } from 'commander';
|
|
6
9
|
import { type InstallCoreOptions, type InstallCoreResult } from './core/install-core.js';
|
|
7
10
|
import { type InstallDocsOptions, type InstallDocsResult } from './docs/install-docs.js';
|
|
@@ -11,12 +14,14 @@ import { type InstallResearchOptions, type InstallResearchResult } from './resea
|
|
|
11
14
|
import { type InstallUtilityOptions, type InstallUtilityResult } from './utility/install-utility.js';
|
|
12
15
|
import { type InstallWorkflowsOptions, type InstallWorkflowsResult } from './workflows/install-workflows.js';
|
|
13
16
|
type InstallScope = 'project' | 'user';
|
|
17
|
+
type PackInstallTarget = InstallScope | 'both';
|
|
14
18
|
export type ToolPack = 'core' | 'ideas' | 'docs' | 'workflows' | 'utility' | 'project-management' | 'research';
|
|
15
|
-
interface InitToolsDependencies {
|
|
19
|
+
export interface InitToolsDependencies {
|
|
16
20
|
buildCommandContext: (options: GlobalOptions) => CommandContext;
|
|
17
21
|
resolveProjectRoot: (cwd: string) => Promise<string>;
|
|
18
22
|
resolveScopeRoot: (scope: InstallScope, cwd: string, home: string) => string;
|
|
19
23
|
resolveAssetsRoot: () => Promise<string>;
|
|
24
|
+
scanTools: (options: ScanToolsOptions) => Promise<ToolInfo[]>;
|
|
20
25
|
selectManyWithAbort: <T extends string>(message: string, choices: MultiSelectChoice<T>[], ctx: PromptContext) => Promise<T[] | null>;
|
|
21
26
|
selectWithAbort: <T extends string>(message: string, choices: SelectChoice<T>[], ctx: PromptContext) => Promise<T | null>;
|
|
22
27
|
installCore: (options: InstallCoreOptions) => Promise<InstallCoreResult>;
|
|
@@ -27,6 +32,8 @@ interface InitToolsDependencies {
|
|
|
27
32
|
installProjectManagement: (options: InstallProjectManagementOptions) => Promise<InstallProjectManagementResult>;
|
|
28
33
|
installResearch: (options: InstallResearchOptions) => Promise<InstallResearchResult>;
|
|
29
34
|
copyDirWithStatus: (source: string, destination: string, force: boolean) => Promise<'copied' | 'updated' | 'skipped'>;
|
|
35
|
+
removeDirectory: (target: string) => Promise<void>;
|
|
36
|
+
removeFile: (target: string) => Promise<void>;
|
|
30
37
|
addLocalPaths: (repoRoot: string, paths: string[]) => Promise<{
|
|
31
38
|
added: string[];
|
|
32
39
|
all: string[];
|
|
@@ -40,9 +47,13 @@ interface InitToolsDependencies {
|
|
|
40
47
|
upsertAgentsMdSection: (repoRoot: string, key: string, body: string) => Promise<UpsertSectionResult>;
|
|
41
48
|
removeAgentsMdSection: (repoRoot: string, key: string) => Promise<boolean>;
|
|
42
49
|
}
|
|
50
|
+
interface InitToolsRunMetadata {
|
|
51
|
+
affectedScopes: ConcreteScope[];
|
|
52
|
+
}
|
|
53
|
+
export declare function consumeInitToolsRunMetadata(): InitToolsRunMetadata | null;
|
|
43
54
|
interface PackScopeInfo {
|
|
44
55
|
pack: ToolPack;
|
|
45
|
-
scope:
|
|
56
|
+
scope: PackInstallTarget;
|
|
46
57
|
}
|
|
47
58
|
export declare function buildToolPacksSectionBody(packs: PackScopeInfo[]): string;
|
|
48
59
|
export declare function runInitTools(context: CommandContext, dependencies: InitToolsDependencies): Promise<ToolPack[]>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/commands/init/tools/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/commands/init/tools/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { rm, unlink } from 'node:fs/promises';
|
|
1
2
|
import { join } from 'node:path';
|
|
2
3
|
import { buildCommandContext, } from '../../../app/command-context.js';
|
|
3
4
|
import { copyDirWithStatus } from '../../init/tools/shared/copy-helpers.js';
|
|
@@ -7,6 +8,7 @@ import { removeAgentsMdSection, upsertAgentsMdSection, } from '../../shared/agen
|
|
|
7
8
|
import { selectManyWithAbort, selectWithAbort, } from '../../shared/shared.prompts.js';
|
|
8
9
|
import { readGlobalOptions } from '../../shared/shared.utils.js';
|
|
9
10
|
import { canonicalPathsForPacks, setInstalledCanonicalPaths, } from '../../tools/shared/install-sync-context.js';
|
|
11
|
+
import { scanTools } from '../../tools/shared/scan-tools.js';
|
|
10
12
|
import { readOatConfig, resolveLocalPaths, writeOatConfig, } from '../../../config/oat-config.js';
|
|
11
13
|
import { resolveAssetsRoot } from '../../../fs/assets.js';
|
|
12
14
|
import { resolveProjectRoot, resolveScopeRoot } from '../../../fs/paths.js';
|
|
@@ -14,38 +16,56 @@ import { Command } from 'commander';
|
|
|
14
16
|
import { createInitToolsCoreCommand } from './core/index.js';
|
|
15
17
|
import { installCore as defaultInstallCore, } from './core/install-core.js';
|
|
16
18
|
import { createInitToolsDocsCommand } from './docs/index.js';
|
|
17
|
-
import {
|
|
19
|
+
import { installDocs as defaultInstallDocs, } from './docs/install-docs.js';
|
|
18
20
|
import { createInitToolsIdeasCommand } from './ideas/index.js';
|
|
19
21
|
import { installIdeas as defaultInstallIdeas, } from './ideas/install-ideas.js';
|
|
22
|
+
import { buildPackInstallStateMap, } from './install-state.js';
|
|
20
23
|
import { createInitToolsProjectManagementCommand } from './project-management/index.js';
|
|
21
24
|
import { installProjectManagement as defaultInstallProjectManagement, } from './project-management/install-project-management.js';
|
|
22
25
|
import { createInitToolsResearchCommand } from './research/index.js';
|
|
23
|
-
import { installResearch as defaultInstallResearch,
|
|
26
|
+
import { installResearch as defaultInstallResearch, } from './research/install-research.js';
|
|
27
|
+
import { DOCS_SKILLS, IDEA_SKILLS, RESEARCH_AGENTS, RESEARCH_SKILLS, UTILITY_SKILLS, } from './shared/skill-manifest.js';
|
|
24
28
|
import { createInitToolsUtilityCommand } from './utility/index.js';
|
|
25
|
-
import { installUtility as defaultInstallUtility,
|
|
29
|
+
import { installUtility as defaultInstallUtility, } from './utility/install-utility.js';
|
|
26
30
|
import { createInitToolsWorkflowsCommand } from './workflows/index.js';
|
|
27
31
|
import { installWorkflows as defaultInstallWorkflows, } from './workflows/install-workflows.js';
|
|
28
32
|
function formatVersionForDisplay(version) {
|
|
29
33
|
return version ?? '(unversioned)';
|
|
30
34
|
}
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
},
|
|
40
|
-
{ label: 'Workflows [project]', value: 'workflows', checked: true },
|
|
41
|
-
{ label: 'Utility [project|user]', value: 'utility', checked: true },
|
|
42
|
-
{ label: 'Research [project|user]', value: 'research', checked: true },
|
|
35
|
+
const ALL_TOOL_PACKS = [
|
|
36
|
+
'core',
|
|
37
|
+
'ideas',
|
|
38
|
+
'docs',
|
|
39
|
+
'workflows',
|
|
40
|
+
'utility',
|
|
41
|
+
'project-management',
|
|
42
|
+
'research',
|
|
43
43
|
];
|
|
44
|
+
const USER_ELIGIBLE_PACK_MEMBERS = {
|
|
45
|
+
ideas: {
|
|
46
|
+
skills: IDEA_SKILLS,
|
|
47
|
+
agents: [],
|
|
48
|
+
},
|
|
49
|
+
docs: {
|
|
50
|
+
skills: DOCS_SKILLS,
|
|
51
|
+
agents: [],
|
|
52
|
+
},
|
|
53
|
+
utility: {
|
|
54
|
+
skills: UTILITY_SKILLS,
|
|
55
|
+
agents: [],
|
|
56
|
+
},
|
|
57
|
+
research: {
|
|
58
|
+
skills: RESEARCH_SKILLS,
|
|
59
|
+
agents: RESEARCH_AGENTS,
|
|
60
|
+
},
|
|
61
|
+
};
|
|
62
|
+
let lastRunInitToolsMetadata = null;
|
|
44
63
|
const DEFAULT_DEPENDENCIES = {
|
|
45
64
|
buildCommandContext,
|
|
46
65
|
resolveProjectRoot,
|
|
47
66
|
resolveScopeRoot,
|
|
48
67
|
resolveAssetsRoot,
|
|
68
|
+
scanTools,
|
|
49
69
|
selectManyWithAbort,
|
|
50
70
|
selectWithAbort,
|
|
51
71
|
installCore: defaultInstallCore,
|
|
@@ -56,6 +76,21 @@ const DEFAULT_DEPENDENCIES = {
|
|
|
56
76
|
installProjectManagement: defaultInstallProjectManagement,
|
|
57
77
|
installResearch: defaultInstallResearch,
|
|
58
78
|
copyDirWithStatus,
|
|
79
|
+
removeDirectory: async (target) => {
|
|
80
|
+
await rm(target, { recursive: true, force: true });
|
|
81
|
+
},
|
|
82
|
+
removeFile: async (target) => {
|
|
83
|
+
try {
|
|
84
|
+
await unlink(target);
|
|
85
|
+
}
|
|
86
|
+
catch (error) {
|
|
87
|
+
if (!(error instanceof Error) ||
|
|
88
|
+
!('code' in error) ||
|
|
89
|
+
error.code !== 'ENOENT') {
|
|
90
|
+
throw error;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
},
|
|
59
94
|
addLocalPaths,
|
|
60
95
|
applyGitignore,
|
|
61
96
|
readOatConfig,
|
|
@@ -70,7 +105,120 @@ const USER_ELIGIBLE_PACKS = new Set([
|
|
|
70
105
|
'utility',
|
|
71
106
|
'research',
|
|
72
107
|
]);
|
|
73
|
-
|
|
108
|
+
function isUserEligiblePack(pack) {
|
|
109
|
+
return USER_ELIGIBLE_PACKS.has(pack);
|
|
110
|
+
}
|
|
111
|
+
async function loadInstalledPackStates(projectRoot, userRoot, assetsRoot, dependencies) {
|
|
112
|
+
const [projectTools, userTools] = await Promise.all([
|
|
113
|
+
dependencies.scanTools({
|
|
114
|
+
scope: 'project',
|
|
115
|
+
scopeRoot: projectRoot,
|
|
116
|
+
assetsRoot,
|
|
117
|
+
}),
|
|
118
|
+
dependencies.scanTools({
|
|
119
|
+
scope: 'user',
|
|
120
|
+
scopeRoot: userRoot,
|
|
121
|
+
assetsRoot,
|
|
122
|
+
}),
|
|
123
|
+
]);
|
|
124
|
+
return buildPackInstallStateMap(ALL_TOOL_PACKS, [
|
|
125
|
+
...projectTools,
|
|
126
|
+
...userTools,
|
|
127
|
+
]);
|
|
128
|
+
}
|
|
129
|
+
function formatInstalledLocation(location) {
|
|
130
|
+
switch (location) {
|
|
131
|
+
case 'project':
|
|
132
|
+
return 'project';
|
|
133
|
+
case 'user':
|
|
134
|
+
return 'user';
|
|
135
|
+
case 'both':
|
|
136
|
+
return 'project + user';
|
|
137
|
+
default:
|
|
138
|
+
return 'not installed';
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
function buildPackChoices(installedPackStates) {
|
|
142
|
+
return [
|
|
143
|
+
{
|
|
144
|
+
label: `Core [user]${installedPackStates.core.location === 'not-installed' ? '' : ` (installed: ${formatInstalledLocation(installedPackStates.core.location)})`}`,
|
|
145
|
+
value: 'core',
|
|
146
|
+
checked: true,
|
|
147
|
+
},
|
|
148
|
+
{
|
|
149
|
+
label: `Ideas [project|user]${installedPackStates.ideas.location === 'not-installed' ? '' : ` (installed: ${formatInstalledLocation(installedPackStates.ideas.location)})`}`,
|
|
150
|
+
value: 'ideas',
|
|
151
|
+
checked: true,
|
|
152
|
+
},
|
|
153
|
+
{
|
|
154
|
+
label: `Docs [project|user]${installedPackStates.docs.location === 'not-installed' ? '' : ` (installed: ${formatInstalledLocation(installedPackStates.docs.location)})`}`,
|
|
155
|
+
value: 'docs',
|
|
156
|
+
checked: true,
|
|
157
|
+
},
|
|
158
|
+
{
|
|
159
|
+
label: `Project Management [project]${installedPackStates['project-management'].location === 'not-installed' ? '' : ` (installed: ${formatInstalledLocation(installedPackStates['project-management'].location)})`}`,
|
|
160
|
+
value: 'project-management',
|
|
161
|
+
checked: false,
|
|
162
|
+
},
|
|
163
|
+
{
|
|
164
|
+
label: `Workflows [project]${installedPackStates.workflows.location === 'not-installed' ? '' : ` (installed: ${formatInstalledLocation(installedPackStates.workflows.location)})`}`,
|
|
165
|
+
value: 'workflows',
|
|
166
|
+
checked: true,
|
|
167
|
+
},
|
|
168
|
+
{
|
|
169
|
+
label: `Utility [project|user]${installedPackStates.utility.location === 'not-installed' ? '' : ` (installed: ${formatInstalledLocation(installedPackStates.utility.location)})`}`,
|
|
170
|
+
value: 'utility',
|
|
171
|
+
checked: true,
|
|
172
|
+
},
|
|
173
|
+
{
|
|
174
|
+
label: `Research [project|user]${installedPackStates.research.location === 'not-installed' ? '' : ` (installed: ${formatInstalledLocation(installedPackStates.research.location)})`}`,
|
|
175
|
+
value: 'research',
|
|
176
|
+
checked: true,
|
|
177
|
+
},
|
|
178
|
+
];
|
|
179
|
+
}
|
|
180
|
+
function buildUserScopeChoices(packs, installedPackStates) {
|
|
181
|
+
return packs.map((pack) => {
|
|
182
|
+
const location = installedPackStates[pack].location;
|
|
183
|
+
return {
|
|
184
|
+
label: location === 'not-installed'
|
|
185
|
+
? pack
|
|
186
|
+
: `${pack} (current: ${formatInstalledLocation(location)})`,
|
|
187
|
+
value: pack,
|
|
188
|
+
checked: location === 'user' || location === 'both',
|
|
189
|
+
};
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
async function resolveBothScopeTarget(pack, dependencies, interactive) {
|
|
193
|
+
const selection = await dependencies.selectWithAbort(`${pack} is currently installed in project and user scope. Keep both installs or normalize to user scope?`, [
|
|
194
|
+
{
|
|
195
|
+
label: 'Keep project + user (recommended)',
|
|
196
|
+
value: 'both',
|
|
197
|
+
description: 'Preserve both installed copies',
|
|
198
|
+
},
|
|
199
|
+
{
|
|
200
|
+
label: 'User only',
|
|
201
|
+
value: 'user',
|
|
202
|
+
description: 'Remove the project-scoped copy',
|
|
203
|
+
},
|
|
204
|
+
], { interactive });
|
|
205
|
+
return selection ?? 'both';
|
|
206
|
+
}
|
|
207
|
+
export function consumeInitToolsRunMetadata() {
|
|
208
|
+
const metadata = lastRunInitToolsMetadata;
|
|
209
|
+
lastRunInitToolsMetadata = null;
|
|
210
|
+
return metadata;
|
|
211
|
+
}
|
|
212
|
+
async function removePackFromScope(pack, root, dependencies) {
|
|
213
|
+
const members = USER_ELIGIBLE_PACK_MEMBERS[pack];
|
|
214
|
+
for (const skill of members.skills) {
|
|
215
|
+
await dependencies.removeDirectory(join(root, '.agents', 'skills', skill));
|
|
216
|
+
}
|
|
217
|
+
for (const agent of members.agents) {
|
|
218
|
+
await dependencies.removeFile(join(root, '.agents', 'agents', agent));
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
async function resolvePackScopes(context, selections, installedPackStates, dependencies) {
|
|
74
222
|
const scopes = {};
|
|
75
223
|
// Workflows is always project-only
|
|
76
224
|
for (const pack of selections) {
|
|
@@ -82,7 +230,7 @@ async function resolvePackScopes(context, selections, dependencies) {
|
|
|
82
230
|
if (selections.includes('core')) {
|
|
83
231
|
scopes.core = 'user';
|
|
84
232
|
}
|
|
85
|
-
const eligiblePacks = selections.filter((pack) =>
|
|
233
|
+
const eligiblePacks = selections.filter((pack) => isUserEligiblePack(pack));
|
|
86
234
|
if (eligiblePacks.length === 0) {
|
|
87
235
|
return scopes;
|
|
88
236
|
}
|
|
@@ -107,31 +255,45 @@ async function resolvePackScopes(context, selections, dependencies) {
|
|
|
107
255
|
return scopes;
|
|
108
256
|
}
|
|
109
257
|
// Interactive: let user pick which packs go to user scope
|
|
110
|
-
const userScopePacks = (await dependencies.selectManyWithAbort('Which packs should install at user scope? (unselected go to project scope)', eligiblePacks.
|
|
111
|
-
label: pack,
|
|
112
|
-
value: pack,
|
|
113
|
-
checked: false,
|
|
114
|
-
})), { interactive: context.interactive })) ?? [];
|
|
258
|
+
const userScopePacks = (await dependencies.selectManyWithAbort('Which packs should install at user scope? (unselected go to project scope)', buildUserScopeChoices(eligiblePacks, installedPackStates), { interactive: context.interactive })) ?? [];
|
|
115
259
|
const userScopeSet = new Set(userScopePacks);
|
|
116
260
|
for (const pack of eligiblePacks) {
|
|
117
|
-
|
|
261
|
+
if (!userScopeSet.has(pack)) {
|
|
262
|
+
scopes[pack] = 'project';
|
|
263
|
+
continue;
|
|
264
|
+
}
|
|
265
|
+
scopes[pack] =
|
|
266
|
+
installedPackStates[pack].location === 'both'
|
|
267
|
+
? await resolveBothScopeTarget(pack, dependencies, context.interactive)
|
|
268
|
+
: 'user';
|
|
118
269
|
}
|
|
119
270
|
return scopes;
|
|
120
271
|
}
|
|
121
|
-
function
|
|
272
|
+
function buildInstalledToolsConfig(selectedPacks, installedPackStates, existingTools) {
|
|
273
|
+
const selectedPackSet = new Set(selectedPacks);
|
|
274
|
+
const tools = { ...existingTools };
|
|
275
|
+
for (const pack of ALL_TOOL_PACKS) {
|
|
276
|
+
tools[pack] =
|
|
277
|
+
selectedPackSet.has(pack) ||
|
|
278
|
+
installedPackStates[pack].location !== 'not-installed';
|
|
279
|
+
}
|
|
280
|
+
return tools;
|
|
281
|
+
}
|
|
282
|
+
function reportSuccess(context, packs, syncScopes) {
|
|
122
283
|
if (context.json) {
|
|
123
284
|
context.logger.json({
|
|
124
285
|
status: 'ok',
|
|
125
|
-
|
|
126
|
-
|
|
286
|
+
installedPacks: packs,
|
|
287
|
+
syncScopes,
|
|
127
288
|
});
|
|
128
289
|
return;
|
|
129
290
|
}
|
|
130
|
-
context.logger.info(`Installed tool packs: ${
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
291
|
+
context.logger.info(`Installed tool packs: ${packs.map(({ pack, scope }) => `${pack} (${formatInstalledLocation(scope)})`).join(', ')}`);
|
|
292
|
+
syncScopes.forEach((scope, index) => {
|
|
293
|
+
context.logger.info(`${index === 0 ? 'Run' : 'Also run'}: oat sync --scope ${scope}`);
|
|
294
|
+
});
|
|
295
|
+
if (syncScopes.length === 0) {
|
|
296
|
+
context.logger.info('No sync needed.');
|
|
135
297
|
}
|
|
136
298
|
}
|
|
137
299
|
function reportOutdatedSkills(context, outdatedSkills) {
|
|
@@ -140,7 +302,7 @@ function reportOutdatedSkills(context, outdatedSkills) {
|
|
|
140
302
|
}
|
|
141
303
|
context.logger.info('Outdated skills:');
|
|
142
304
|
for (const skill of outdatedSkills) {
|
|
143
|
-
context.logger.info(` ${skill.name} ${formatVersionForDisplay(skill.installed)} -> ${formatVersionForDisplay(skill.bundled)}`);
|
|
305
|
+
context.logger.info(` ${skill.name} (${skill.targetRoot}) ${formatVersionForDisplay(skill.installed)} -> ${formatVersionForDisplay(skill.bundled)}`);
|
|
144
306
|
}
|
|
145
307
|
}
|
|
146
308
|
async function updateOutdatedSkills(outdatedSkills, assetsRoot, dependencies) {
|
|
@@ -163,7 +325,7 @@ const PACK_DESCRIPTIONS = {
|
|
|
163
325
|
research: 'Research, analysis, verification, and synthesis',
|
|
164
326
|
};
|
|
165
327
|
export function buildToolPacksSectionBody(packs) {
|
|
166
|
-
const userPacks = packs.filter((p) => p.scope === 'user');
|
|
328
|
+
const userPacks = packs.filter((p) => p.scope === 'user' || p.scope === 'both');
|
|
167
329
|
const hasWorkflows = packs.some((p) => p.pack === 'workflows');
|
|
168
330
|
const lines = [
|
|
169
331
|
'## Tool Packs',
|
|
@@ -179,7 +341,11 @@ export function buildToolPacksSectionBody(packs) {
|
|
|
179
341
|
}
|
|
180
342
|
lines.push('', '### Installed Packs', '');
|
|
181
343
|
for (const { pack, scope } of packs) {
|
|
182
|
-
const suffix = scope === 'user'
|
|
344
|
+
const suffix = scope === 'user'
|
|
345
|
+
? ' _(user scope)_'
|
|
346
|
+
: scope === 'both'
|
|
347
|
+
? ' _(project + user scope)_'
|
|
348
|
+
: '';
|
|
183
349
|
lines.push(`- **${pack}** — ${PACK_DESCRIPTIONS[pack]}${suffix}`);
|
|
184
350
|
}
|
|
185
351
|
if (hasWorkflows) {
|
|
@@ -188,66 +354,118 @@ export function buildToolPacksSectionBody(packs) {
|
|
|
188
354
|
return lines.join('\n');
|
|
189
355
|
}
|
|
190
356
|
export async function runInitTools(context, dependencies) {
|
|
357
|
+
lastRunInitToolsMetadata = null;
|
|
191
358
|
try {
|
|
359
|
+
const projectRoot = await dependencies.resolveProjectRoot(context.cwd);
|
|
360
|
+
const userRoot = dependencies.resolveScopeRoot('user', context.cwd, context.home);
|
|
361
|
+
const assetsRoot = await dependencies.resolveAssetsRoot();
|
|
362
|
+
const initialPackStates = await loadInstalledPackStates(projectRoot, userRoot, assetsRoot, dependencies);
|
|
192
363
|
const selectedPacks = context.interactive
|
|
193
|
-
? ((await dependencies.selectManyWithAbort('Select tool packs to install',
|
|
364
|
+
? ((await dependencies.selectManyWithAbort('Select tool packs to install', buildPackChoices(initialPackStates), { interactive: context.interactive })) ?? [])
|
|
194
365
|
: ['core', 'ideas', 'docs', 'workflows', 'utility', 'research'];
|
|
195
366
|
if (!context.interactive) {
|
|
196
367
|
selectedPacks.push('project-management');
|
|
197
368
|
}
|
|
198
369
|
if (selectedPacks.length === 0) {
|
|
370
|
+
lastRunInitToolsMetadata = { affectedScopes: [] };
|
|
199
371
|
if (!context.json) {
|
|
200
372
|
context.logger.info('No tool packs selected.');
|
|
201
373
|
}
|
|
202
374
|
process.exitCode = 0;
|
|
203
375
|
return [];
|
|
204
376
|
}
|
|
205
|
-
const
|
|
206
|
-
const userRoot = dependencies.resolveScopeRoot('user', context.cwd, context.home);
|
|
207
|
-
const packScopes = await resolvePackScopes(context, selectedPacks, dependencies);
|
|
377
|
+
const packScopes = await resolvePackScopes(context, selectedPacks, initialPackStates, dependencies);
|
|
208
378
|
function packRoot(pack) {
|
|
209
379
|
return packScopes[pack] === 'user' ? userRoot : projectRoot;
|
|
210
380
|
}
|
|
211
|
-
|
|
381
|
+
function packTargets(pack) {
|
|
382
|
+
return packScopes[pack] === 'both'
|
|
383
|
+
? [projectRoot, userRoot]
|
|
384
|
+
: [packRoot(pack)];
|
|
385
|
+
}
|
|
212
386
|
const outdatedSkills = [];
|
|
387
|
+
const affectedScopes = new Set();
|
|
388
|
+
for (const pack of selectedPacks) {
|
|
389
|
+
if (!isUserEligiblePack(pack)) {
|
|
390
|
+
continue;
|
|
391
|
+
}
|
|
392
|
+
const desiredScope = packScopes[pack];
|
|
393
|
+
const currentLocation = initialPackStates[pack].location;
|
|
394
|
+
if (desiredScope === 'both') {
|
|
395
|
+
continue;
|
|
396
|
+
}
|
|
397
|
+
if (desiredScope === 'user') {
|
|
398
|
+
if (currentLocation === 'project' || currentLocation === 'both') {
|
|
399
|
+
await removePackFromScope(pack, projectRoot, dependencies);
|
|
400
|
+
affectedScopes.add('project');
|
|
401
|
+
}
|
|
402
|
+
continue;
|
|
403
|
+
}
|
|
404
|
+
if (currentLocation === 'user' || currentLocation === 'both') {
|
|
405
|
+
await removePackFromScope(pack, userRoot, dependencies);
|
|
406
|
+
affectedScopes.add('user');
|
|
407
|
+
}
|
|
408
|
+
}
|
|
213
409
|
if (selectedPacks.includes('core')) {
|
|
214
410
|
// Core pack always installs at user scope, regardless of userEligibleScope
|
|
411
|
+
affectedScopes.add('user');
|
|
215
412
|
const coreResult = await dependencies.installCore({
|
|
216
413
|
assetsRoot,
|
|
217
414
|
targetRoot: userRoot,
|
|
218
415
|
});
|
|
219
416
|
for (const skill of coreResult.outdatedSkills) {
|
|
220
|
-
outdatedSkills.push({
|
|
417
|
+
outdatedSkills.push({
|
|
418
|
+
...skill,
|
|
419
|
+
targetRoot: userRoot,
|
|
420
|
+
selectionKey: `${skill.name}:${userRoot}`,
|
|
421
|
+
});
|
|
221
422
|
}
|
|
222
423
|
}
|
|
223
424
|
if (selectedPacks.includes('ideas')) {
|
|
224
|
-
const targetRoot
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
425
|
+
for (const targetRoot of packTargets('ideas')) {
|
|
426
|
+
affectedScopes.add(targetRoot === userRoot ? 'user' : 'project');
|
|
427
|
+
const ideasResult = await dependencies.installIdeas({
|
|
428
|
+
assetsRoot,
|
|
429
|
+
targetRoot,
|
|
430
|
+
});
|
|
431
|
+
for (const skill of ideasResult.outdatedSkills) {
|
|
432
|
+
outdatedSkills.push({
|
|
433
|
+
...skill,
|
|
434
|
+
targetRoot,
|
|
435
|
+
selectionKey: `${skill.name}:${targetRoot}`,
|
|
436
|
+
});
|
|
437
|
+
}
|
|
231
438
|
}
|
|
232
439
|
}
|
|
233
440
|
if (selectedPacks.includes('docs')) {
|
|
234
|
-
const targetRoot
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
441
|
+
for (const targetRoot of packTargets('docs')) {
|
|
442
|
+
affectedScopes.add(targetRoot === userRoot ? 'user' : 'project');
|
|
443
|
+
const docsResult = await dependencies.installDocs({
|
|
444
|
+
assetsRoot,
|
|
445
|
+
targetRoot,
|
|
446
|
+
skills: [...DOCS_SKILLS],
|
|
447
|
+
});
|
|
448
|
+
for (const skill of docsResult.outdatedSkills) {
|
|
449
|
+
outdatedSkills.push({
|
|
450
|
+
...skill,
|
|
451
|
+
targetRoot,
|
|
452
|
+
selectionKey: `${skill.name}:${targetRoot}`,
|
|
453
|
+
});
|
|
454
|
+
}
|
|
242
455
|
}
|
|
243
456
|
}
|
|
244
457
|
if (selectedPacks.includes('workflows')) {
|
|
458
|
+
affectedScopes.add('project');
|
|
245
459
|
const workflowsResult = await dependencies.installWorkflows({
|
|
246
460
|
assetsRoot,
|
|
247
461
|
targetRoot: projectRoot,
|
|
248
462
|
});
|
|
249
463
|
for (const skill of workflowsResult.outdatedSkills) {
|
|
250
|
-
outdatedSkills.push({
|
|
464
|
+
outdatedSkills.push({
|
|
465
|
+
...skill,
|
|
466
|
+
targetRoot: projectRoot,
|
|
467
|
+
selectionKey: `${skill.name}:${projectRoot}`,
|
|
468
|
+
});
|
|
251
469
|
}
|
|
252
470
|
const resolvedRoot = workflowsResult.resolvedProjectsRoot || '.oat/projects/shared';
|
|
253
471
|
const projectsBase = resolvedRoot.replace(/\/[^/]+$/, '');
|
|
@@ -286,47 +504,64 @@ export async function runInitTools(context, dependencies) {
|
|
|
286
504
|
}
|
|
287
505
|
}
|
|
288
506
|
if (selectedPacks.includes('utility')) {
|
|
289
|
-
const targetRoot
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
507
|
+
for (const targetRoot of packTargets('utility')) {
|
|
508
|
+
affectedScopes.add(targetRoot === userRoot ? 'user' : 'project');
|
|
509
|
+
const utilityResult = await dependencies.installUtility({
|
|
510
|
+
assetsRoot,
|
|
511
|
+
targetRoot,
|
|
512
|
+
skills: [...UTILITY_SKILLS],
|
|
513
|
+
});
|
|
514
|
+
for (const skill of utilityResult.outdatedSkills) {
|
|
515
|
+
outdatedSkills.push({
|
|
516
|
+
...skill,
|
|
517
|
+
targetRoot,
|
|
518
|
+
selectionKey: `${skill.name}:${targetRoot}`,
|
|
519
|
+
});
|
|
520
|
+
}
|
|
297
521
|
}
|
|
298
522
|
}
|
|
299
523
|
if (selectedPacks.includes('project-management')) {
|
|
300
524
|
const targetRoot = projectRoot;
|
|
525
|
+
affectedScopes.add('project');
|
|
301
526
|
const projectManagementResult = await dependencies.installProjectManagement({
|
|
302
527
|
assetsRoot,
|
|
303
528
|
targetRoot,
|
|
304
529
|
});
|
|
305
530
|
for (const skill of projectManagementResult.outdatedSkills) {
|
|
306
|
-
outdatedSkills.push({
|
|
531
|
+
outdatedSkills.push({
|
|
532
|
+
...skill,
|
|
533
|
+
targetRoot,
|
|
534
|
+
selectionKey: `${skill.name}:${targetRoot}`,
|
|
535
|
+
});
|
|
307
536
|
}
|
|
308
537
|
}
|
|
309
538
|
if (selectedPacks.includes('research')) {
|
|
310
|
-
const targetRoot
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
539
|
+
for (const targetRoot of packTargets('research')) {
|
|
540
|
+
affectedScopes.add(targetRoot === userRoot ? 'user' : 'project');
|
|
541
|
+
const researchResult = await dependencies.installResearch({
|
|
542
|
+
assetsRoot,
|
|
543
|
+
targetRoot,
|
|
544
|
+
skills: [...RESEARCH_SKILLS],
|
|
545
|
+
});
|
|
546
|
+
for (const skill of researchResult.outdatedSkills) {
|
|
547
|
+
outdatedSkills.push({
|
|
548
|
+
...skill,
|
|
549
|
+
targetRoot,
|
|
550
|
+
selectionKey: `${skill.name}:${targetRoot}`,
|
|
551
|
+
});
|
|
552
|
+
}
|
|
318
553
|
}
|
|
319
554
|
}
|
|
320
555
|
if (outdatedSkills.length > 0) {
|
|
321
556
|
reportOutdatedSkills(context, outdatedSkills);
|
|
322
557
|
if (context.interactive) {
|
|
323
558
|
const selectedNames = (await dependencies.selectManyWithAbort('Update outdated skills?', outdatedSkills.map((skill) => ({
|
|
324
|
-
label: `${skill.name} (${skill.installed} -> ${skill.bundled})`,
|
|
325
|
-
value: skill.
|
|
559
|
+
label: `${skill.name} (${skill.targetRoot}) (${skill.installed} -> ${skill.bundled})`,
|
|
560
|
+
value: skill.selectionKey,
|
|
326
561
|
checked: true,
|
|
327
562
|
})), { interactive: context.interactive })) ?? [];
|
|
328
563
|
const selectedSet = new Set(selectedNames);
|
|
329
|
-
const selectedOutdated = outdatedSkills.filter((skill) => selectedSet.has(skill.
|
|
564
|
+
const selectedOutdated = outdatedSkills.filter((skill) => selectedSet.has(skill.selectionKey));
|
|
330
565
|
const updatedNames = await updateOutdatedSkills(selectedOutdated, assetsRoot, dependencies);
|
|
331
566
|
if (updatedNames.length > 0) {
|
|
332
567
|
context.logger.info(`Updated outdated skills: ${updatedNames.join(', ')}`);
|
|
@@ -349,17 +584,18 @@ export async function runInitTools(context, dependencies) {
|
|
|
349
584
|
context.logger.info(`AGENTS.md tool packs section ${sectionResult.action}.`);
|
|
350
585
|
}
|
|
351
586
|
const config = await dependencies.readOatConfig(projectRoot);
|
|
352
|
-
const tools =
|
|
353
|
-
for (const pack of selectedPacks) {
|
|
354
|
-
tools[pack] = true;
|
|
355
|
-
}
|
|
587
|
+
const tools = buildInstalledToolsConfig(selectedPacks, initialPackStates, config.tools);
|
|
356
588
|
await dependencies.writeOatConfig(projectRoot, { ...config, tools });
|
|
357
|
-
const
|
|
358
|
-
|
|
589
|
+
const affectedScopesList = [...affectedScopes];
|
|
590
|
+
lastRunInitToolsMetadata = {
|
|
591
|
+
affectedScopes: affectedScopesList,
|
|
592
|
+
};
|
|
593
|
+
reportSuccess(context, packScopeInfo, affectedScopesList);
|
|
359
594
|
process.exitCode = 0;
|
|
360
595
|
return selectedPacks;
|
|
361
596
|
}
|
|
362
597
|
catch (error) {
|
|
598
|
+
lastRunInitToolsMetadata = null;
|
|
363
599
|
const message = error instanceof Error ? error.message : String(error);
|
|
364
600
|
if (context.json) {
|
|
365
601
|
context.logger.json({ status: 'error', message });
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { PackName, ToolInfo } from '../../tools/shared/types.js';
|
|
2
|
+
export type PackInstallLocation = 'not-installed' | 'project' | 'user' | 'both';
|
|
3
|
+
export interface PackInstallState {
|
|
4
|
+
project: boolean;
|
|
5
|
+
user: boolean;
|
|
6
|
+
location: PackInstallLocation;
|
|
7
|
+
}
|
|
8
|
+
export declare function resolvePackInstallLocation(project: boolean, user: boolean): PackInstallLocation;
|
|
9
|
+
export declare function buildPackInstallStateMap<TPack extends PackName>(packs: readonly TPack[], tools: ToolInfo[]): Record<TPack, PackInstallState>;
|
|
10
|
+
//# sourceMappingURL=install-state.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"install-state.d.ts","sourceRoot":"","sources":["../../../../src/commands/init/tools/install-state.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,8BAA8B,CAAC;AAEvE,MAAM,MAAM,mBAAmB,GAAG,eAAe,GAAG,SAAS,GAAG,MAAM,GAAG,MAAM,CAAC;AAEhF,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,OAAO,CAAC;IACd,QAAQ,EAAE,mBAAmB,CAAC;CAC/B;AAED,wBAAgB,0BAA0B,CACxC,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE,OAAO,GACZ,mBAAmB,CAcrB;AAED,wBAAgB,wBAAwB,CAAC,KAAK,SAAS,QAAQ,EAC7D,KAAK,EAAE,SAAS,KAAK,EAAE,EACvB,KAAK,EAAE,QAAQ,EAAE,GAChB,MAAM,CAAC,KAAK,EAAE,gBAAgB,CAAC,CA8BjC"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
export function resolvePackInstallLocation(project, user) {
|
|
2
|
+
if (project && user) {
|
|
3
|
+
return 'both';
|
|
4
|
+
}
|
|
5
|
+
if (project) {
|
|
6
|
+
return 'project';
|
|
7
|
+
}
|
|
8
|
+
if (user) {
|
|
9
|
+
return 'user';
|
|
10
|
+
}
|
|
11
|
+
return 'not-installed';
|
|
12
|
+
}
|
|
13
|
+
export function buildPackInstallStateMap(packs, tools) {
|
|
14
|
+
const state = Object.fromEntries(packs.map((pack) => [
|
|
15
|
+
pack,
|
|
16
|
+
{
|
|
17
|
+
project: false,
|
|
18
|
+
user: false,
|
|
19
|
+
location: 'not-installed',
|
|
20
|
+
},
|
|
21
|
+
]));
|
|
22
|
+
for (const tool of tools) {
|
|
23
|
+
if (tool.pack === 'custom' || !(tool.pack in state)) {
|
|
24
|
+
continue;
|
|
25
|
+
}
|
|
26
|
+
const packState = state[tool.pack];
|
|
27
|
+
if (tool.scope === 'project') {
|
|
28
|
+
packState.project = true;
|
|
29
|
+
}
|
|
30
|
+
else {
|
|
31
|
+
packState.user = true;
|
|
32
|
+
}
|
|
33
|
+
packState.location = resolvePackInstallLocation(packState.project, packState.user);
|
|
34
|
+
}
|
|
35
|
+
return state;
|
|
36
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
+
import { type InitToolsDependencies } from '../../init/tools/index.js';
|
|
1
2
|
import { type AutoSyncDependencies } from '../../tools/shared/auto-sync.js';
|
|
2
3
|
import type { Command } from 'commander';
|
|
3
|
-
export declare function createToolsInstallCommand(syncDependencies?: AutoSyncDependencies, createBaseCommand?: () => Command): Command;
|
|
4
|
+
export declare function createToolsInstallCommand(syncDependencies?: AutoSyncDependencies, initOverrides?: Partial<InitToolsDependencies>, createBaseCommand?: () => Command): Command;
|
|
4
5
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/commands/tools/install/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/commands/tools/install/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAGL,KAAK,qBAAqB,EAC3B,MAAM,sBAAsB,CAAC;AAK9B,OAAO,EACL,KAAK,oBAAoB,EAE1B,MAAM,kCAAkC,CAAC;AAE1C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAwBzC,wBAAgB,yBAAyB,CACvC,gBAAgB,GAAE,oBAA8C,EAChE,aAAa,GAAE,OAAO,CAAC,qBAAqB,CAAM,EAClD,iBAAiB,CAAC,EAAE,MAAM,OAAO,GAChC,OAAO,CAoCT"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { execFile } from 'node:child_process';
|
|
2
2
|
import { buildCommandContext } from '../../../app/command-context.js';
|
|
3
|
-
import { createInitToolsCommand } from '../../init/tools/index.js';
|
|
3
|
+
import { consumeInitToolsRunMetadata, createInitToolsCommand, } from '../../init/tools/index.js';
|
|
4
4
|
import { readGlobalOptions, resolveConcreteScopes, } from '../../shared/shared.utils.js';
|
|
5
5
|
import { autoSync, } from '../../tools/shared/auto-sync.js';
|
|
6
6
|
import { getInstalledCanonicalPaths as getInstallSyncCanonicalPaths } from '../../tools/shared/install-sync-context.js';
|
|
@@ -26,8 +26,10 @@ const defaultSyncDependencies = {
|
|
|
26
26
|
});
|
|
27
27
|
},
|
|
28
28
|
};
|
|
29
|
-
export function createToolsInstallCommand(syncDependencies = defaultSyncDependencies,
|
|
30
|
-
const cmd = createBaseCommand
|
|
29
|
+
export function createToolsInstallCommand(syncDependencies = defaultSyncDependencies, initOverrides = {}, createBaseCommand) {
|
|
30
|
+
const cmd = createBaseCommand === undefined
|
|
31
|
+
? createInitToolsCommand(initOverrides)
|
|
32
|
+
: createBaseCommand();
|
|
31
33
|
cmd.name('install');
|
|
32
34
|
cmd.option('--no-sync', 'Skip auto-sync after install');
|
|
33
35
|
cmd.hook('postAction', async (thisCommand, actionCommand) => {
|
|
@@ -37,8 +39,12 @@ export function createToolsInstallCommand(syncDependencies = defaultSyncDependen
|
|
|
37
39
|
if (opts.sync === false)
|
|
38
40
|
return;
|
|
39
41
|
const globalOptions = readGlobalOptions(actionCommand);
|
|
40
|
-
const
|
|
41
|
-
const
|
|
42
|
+
const buildContext = initOverrides.buildCommandContext ?? buildCommandContext;
|
|
43
|
+
const context = buildContext(globalOptions);
|
|
44
|
+
const metadata = consumeInitToolsRunMetadata();
|
|
45
|
+
const scopes = metadata === null
|
|
46
|
+
? resolveConcreteScopes(context.scope)
|
|
47
|
+
: metadata.affectedScopes;
|
|
42
48
|
const installedCanonicalPaths = getInstallSyncCanonicalPaths(actionCommand);
|
|
43
49
|
await autoSync(scopes, context.cwd, context.home, context.logger, syncDependencies, { installedCanonicalPaths });
|
|
44
50
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@open-agent-toolkit/cli",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.36",
|
|
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",
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
"ora": "^9.0.0",
|
|
34
34
|
"yaml": "2.8.2",
|
|
35
35
|
"zod": "^3.25.76",
|
|
36
|
-
"@open-agent-toolkit/control-plane": "0.0.
|
|
36
|
+
"@open-agent-toolkit/control-plane": "0.0.36"
|
|
37
37
|
},
|
|
38
38
|
"devDependencies": {
|
|
39
39
|
"@types/node": "^22.10.0",
|