@open-agent-toolkit/cli 0.1.62 → 0.1.63

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.
Files changed (51) hide show
  1. package/assets/docs/cli-utilities/configuration.md +29 -0
  2. package/assets/docs/cli-utilities/tool-packs.md +29 -1
  3. package/assets/docs/workflows/projects/autonomy.md +154 -0
  4. package/assets/docs/workflows/projects/cursor-cloud.md +151 -0
  5. package/assets/docs/workflows/projects/index.md +6 -0
  6. package/assets/public-package-versions.json +4 -4
  7. package/assets/skills/oat-cursor-cloud-projects/SKILL.md +318 -0
  8. package/assets/skills/oat-cursor-cloud-projects/references/cursor-cloud-mechanics.md +173 -0
  9. package/assets/skills/oat-project-autonomous/SKILL.md +439 -0
  10. package/assets/skills/oat-project-autonomous/references/gate-inventory.md +294 -0
  11. package/assets/skills/oat-project-design/SKILL.md +79 -1
  12. package/assets/skills/oat-project-discover/SKILL.md +76 -1
  13. package/assets/skills/oat-project-document/SKILL.md +17 -1
  14. package/assets/skills/oat-project-document/references/docs/autonomy-contract.md +294 -0
  15. package/assets/skills/oat-project-implement/SKILL.md +18 -1
  16. package/assets/skills/oat-project-implement/references/completion-and-closeout.md +72 -7
  17. package/assets/skills/oat-project-implement/references/dispatch-and-dry-run.md +17 -9
  18. package/assets/skills/oat-project-implement/references/docs/autonomy-contract.md +294 -0
  19. package/assets/skills/oat-project-implement/references/plan-and-resume.md +56 -0
  20. package/assets/skills/oat-project-pr-final/SKILL.md +23 -4
  21. package/assets/skills/oat-project-pr-final/references/docs/autonomy-contract.md +294 -0
  22. package/assets/skills/oat-project-quick-start/SKILL.md +43 -2
  23. package/assets/skills/oat-project-quick-start/references/docs/autonomy-contract.md +294 -0
  24. package/assets/skills/oat-project-summary/SKILL.md +69 -14
  25. package/assets/templates/summary.md +24 -0
  26. package/dist/commands/init/tools/index.d.ts.map +1 -1
  27. package/dist/commands/init/tools/index.js +67 -45
  28. package/dist/commands/init/tools/shared/skill-manifest.d.ts +1 -1
  29. package/dist/commands/init/tools/shared/skill-manifest.d.ts.map +1 -1
  30. package/dist/commands/init/tools/shared/skill-manifest.js +2 -0
  31. package/dist/commands/init/tools/workflows/index.d.ts +2 -1
  32. package/dist/commands/init/tools/workflows/index.d.ts.map +1 -1
  33. package/dist/commands/init/tools/workflows/index.js +13 -11
  34. package/dist/commands/init/tools/workflows/install-workflows.d.ts +2 -0
  35. package/dist/commands/init/tools/workflows/install-workflows.d.ts.map +1 -1
  36. package/dist/commands/init/tools/workflows/install-workflows.js +4 -0
  37. package/dist/commands/project/new/scaffold.d.ts +1 -0
  38. package/dist/commands/project/new/scaffold.d.ts.map +1 -1
  39. package/dist/commands/project/new/scaffold.js +23 -4
  40. package/dist/commands/tools/remove/index.js +2 -2
  41. package/dist/commands/tools/remove/remove-tools.d.ts.map +1 -1
  42. package/dist/commands/tools/remove/remove-tools.js +23 -0
  43. package/dist/commands/tools/update/index.d.ts.map +1 -1
  44. package/dist/commands/tools/update/index.js +7 -1
  45. package/dist/commands/tools/update/update-tools.d.ts +9 -0
  46. package/dist/commands/tools/update/update-tools.d.ts.map +1 -1
  47. package/dist/commands/tools/update/update-tools.js +25 -5
  48. package/dist/providers/identity/family.d.ts +1 -1
  49. package/dist/providers/identity/family.d.ts.map +1 -1
  50. package/dist/providers/identity/family.js +2 -0
  51. package/package.json +2 -2
@@ -26,7 +26,7 @@ import { createInitToolsProjectManagementCommand } from './project-management/in
26
26
  import { installProjectManagement as defaultInstallProjectManagement, } from './project-management/install-project-management.js';
27
27
  import { createInitToolsResearchCommand } from './research/index.js';
28
28
  import { installResearch as defaultInstallResearch, } from './research/install-research.js';
29
- import { BRAINSTORM_SKILLS, DOCS_SKILLS, IDEA_SKILLS, RESEARCH_AGENTS, RESEARCH_SKILLS, UTILITY_SKILLS, resolvePackDefaultScope, } from './shared/skill-manifest.js';
29
+ import { BRAINSTORM_SKILLS, DOCS_SKILLS, IDEA_SKILLS, RESEARCH_AGENTS, RESEARCH_SKILLS, UTILITY_SKILLS, WORKFLOW_AGENTS, WORKFLOW_SCRIPTS, WORKFLOW_SKILLS, WORKFLOW_TEMPLATES, resolvePackDefaultScope, } from './shared/skill-manifest.js';
30
30
  import { createInitToolsUtilityCommand } from './utility/index.js';
31
31
  import { installUtility as defaultInstallUtility, } from './utility/install-utility.js';
32
32
  import { createInitToolsWorkflowsCommand } from './workflows/index.js';
@@ -53,6 +53,10 @@ const USER_ELIGIBLE_PACK_MEMBERS = {
53
53
  skills: DOCS_SKILLS,
54
54
  agents: [],
55
55
  },
56
+ workflows: {
57
+ skills: WORKFLOW_SKILLS,
58
+ agents: WORKFLOW_AGENTS,
59
+ },
56
60
  utility: {
57
61
  skills: UTILITY_SKILLS,
58
62
  agents: [],
@@ -110,6 +114,7 @@ const DEFAULT_DEPENDENCIES = {
110
114
  const USER_ELIGIBLE_PACKS = new Set([
111
115
  'ideas',
112
116
  'docs',
117
+ 'workflows',
113
118
  'utility',
114
119
  'research',
115
120
  'brainstorm',
@@ -241,7 +246,7 @@ function buildPackChoices(installedPackStates) {
241
246
  checked: false,
242
247
  },
243
248
  {
244
- label: `Workflows [project]${installedPackStates.workflows.location === 'not-installed' ? '' : ` (installed: ${formatInstalledLocation(installedPackStates.workflows.location)})`}`,
249
+ label: `Workflows [project|user]${installedPackStates.workflows.location === 'not-installed' ? '' : ` (installed: ${formatInstalledLocation(installedPackStates.workflows.location)})`}`,
245
250
  value: 'workflows',
246
251
  checked: true,
247
252
  },
@@ -275,6 +280,14 @@ async function removePackFromScope(pack, root, dependencies) {
275
280
  for (const agent of members.agents) {
276
281
  await dependencies.removeFile(join(root, '.agents', 'agents', agent));
277
282
  }
283
+ if (pack === 'workflows') {
284
+ for (const template of WORKFLOW_TEMPLATES) {
285
+ await dependencies.removeFile(join(root, '.oat', 'templates', template));
286
+ }
287
+ for (const script of WORKFLOW_SCRIPTS) {
288
+ await dependencies.removeFile(join(root, '.oat', 'scripts', script));
289
+ }
290
+ }
278
291
  }
279
292
  /**
280
293
  * Resolve a possibly-deferred scope-selection signal into a concrete mode.
@@ -311,7 +324,7 @@ async function resolveDeferredGate(scopeSelection, interactive, dependencies) {
311
324
  }
312
325
  async function resolvePackScopes(context, selections, installedPackStates, dependencies) {
313
326
  const scopes = {};
314
- // Workflows is always project-only
327
+ // Packs outside the user-eligible set are project-only.
315
328
  for (const pack of selections) {
316
329
  if (!USER_ELIGIBLE_PACKS.has(pack)) {
317
330
  scopes[pack] = 'project';
@@ -684,50 +697,59 @@ export async function runInitTools(context, dependencies) {
684
697
  }
685
698
  }
686
699
  if (selectedPacks.includes('workflows')) {
687
- affectedScopes.add('project');
688
- const workflowsResult = await dependencies.installWorkflows({
689
- assetsRoot,
690
- targetRoot: projectRoot,
691
- });
692
- for (const skill of workflowsResult.outdatedSkills) {
693
- outdatedSkills.push({
694
- ...skill,
695
- targetRoot: projectRoot,
696
- selectionKey: `${skill.name}:${projectRoot}`,
700
+ const workflowsAdded = addedScopes('workflows');
701
+ for (const targetRoot of packTargets('workflows')) {
702
+ const targetScope = targetRoot === userRoot ? 'user' : 'project';
703
+ if (workflowsAdded.has(targetScope)) {
704
+ affectedScopes.add(targetScope);
705
+ }
706
+ const workflowsResult = await dependencies.installWorkflows({
707
+ assetsRoot,
708
+ targetRoot,
709
+ scope: targetScope,
697
710
  });
698
- }
699
- const resolvedRoot = workflowsResult.resolvedProjectsRoot || '.oat/projects/shared';
700
- const projectsBase = resolvedRoot.replace(/\/[^/]+$/, '');
701
- const PR_ARCHIVE_LOCAL_PATHS = [
702
- `${projectsBase}/**/pr`,
703
- `${projectsBase}/**/reviews/archived`,
704
- ];
705
- const existingConfig = await dependencies.readOatConfig(projectRoot);
706
- const existingLocalPaths = new Set(dependencies.resolveLocalPaths(existingConfig));
707
- const alreadyConfigured = PR_ARCHIVE_LOCAL_PATHS.every((p) => existingLocalPaths.has(p));
708
- if (!alreadyConfigured) {
709
- let makeLocal = true;
710
- if (context.interactive) {
711
- const selected = await dependencies.selectWithAbort('Should shared-project PR directories and archived review history be local-only (gitignored) or version-controlled?', [
712
- {
713
- label: 'Local only (recommended)',
714
- value: 'local',
715
- description: 'PR artifacts and archived reviews stay local; active reviews remain tracked until received',
716
- },
717
- {
718
- label: 'Version controlled',
719
- value: 'tracked',
720
- description: 'PR artifacts and archived reviews are committed to the repo too',
721
- },
722
- ], { interactive: context.interactive });
723
- makeLocal = selected !== 'tracked';
711
+ for (const skill of workflowsResult.outdatedSkills) {
712
+ outdatedSkills.push({
713
+ ...skill,
714
+ targetRoot,
715
+ selectionKey: `${skill.name}:${targetRoot}`,
716
+ });
724
717
  }
725
- if (makeLocal) {
726
- const addResult = await dependencies.addLocalPaths(projectRoot, PR_ARCHIVE_LOCAL_PATHS);
727
- if (addResult.added.length > 0) {
728
- const config = await dependencies.readOatConfig(projectRoot);
729
- const allPaths = dependencies.resolveLocalPaths(config);
730
- await dependencies.applyGitignore(projectRoot, allPaths);
718
+ if (targetScope === 'project') {
719
+ const resolvedRoot = workflowsResult.resolvedProjectsRoot || '.oat/projects/shared';
720
+ const projectsBase = resolvedRoot.replace(/\/[^/]+$/, '');
721
+ const PR_ARCHIVE_LOCAL_PATHS = [
722
+ `${projectsBase}/**/pr`,
723
+ `${projectsBase}/**/reviews/archived`,
724
+ ];
725
+ const existingConfig = await dependencies.readOatConfig(projectRoot);
726
+ const existingLocalPaths = new Set(dependencies.resolveLocalPaths(existingConfig));
727
+ const alreadyConfigured = PR_ARCHIVE_LOCAL_PATHS.every((p) => existingLocalPaths.has(p));
728
+ if (!alreadyConfigured) {
729
+ let makeLocal = true;
730
+ if (context.interactive) {
731
+ const selected = await dependencies.selectWithAbort('Should shared-project PR directories and archived review history be local-only (gitignored) or version-controlled?', [
732
+ {
733
+ label: 'Local only (recommended)',
734
+ value: 'local',
735
+ description: 'PR artifacts and archived reviews stay local; active reviews remain tracked until received',
736
+ },
737
+ {
738
+ label: 'Version controlled',
739
+ value: 'tracked',
740
+ description: 'PR artifacts and archived reviews are committed to the repo too',
741
+ },
742
+ ], { interactive: context.interactive });
743
+ makeLocal = selected !== 'tracked';
744
+ }
745
+ if (makeLocal) {
746
+ const addResult = await dependencies.addLocalPaths(projectRoot, PR_ARCHIVE_LOCAL_PATHS);
747
+ if (addResult.added.length > 0) {
748
+ const config = await dependencies.readOatConfig(projectRoot);
749
+ const allPaths = dependencies.resolveLocalPaths(config);
750
+ await dependencies.applyGitignore(projectRoot, allPaths);
751
+ }
752
+ }
731
753
  }
732
754
  }
733
755
  }
@@ -11,7 +11,7 @@ export interface PackMetadata {
11
11
  }
12
12
  export declare const PACK_METADATA: Record<string, PackMetadata>;
13
13
  export declare function resolvePackDefaultScope(packName: string): 'user' | 'project';
14
- export declare const WORKFLOW_SKILLS: readonly ["oat-project-capture", "oat-project-clear-active", "oat-project-complete", "oat-project-design", "oat-project-dispatch-subagents", "oat-project-discover", "oat-project-document", "oat-project-implement", "oat-project-import-plan", "oat-project-new", "oat-project-next", "oat-project-open", "oat-project-plan", "oat-project-plan-writing", "oat-project-pr-final", "oat-project-pr-progress", "oat-project-progress", "oat-project-promote-spec-driven", "oat-project-quick-start", "oat-project-reconcile", "oat-project-revise", "oat-project-review-provide", "oat-project-review-provide-remote", "oat-project-review-receive", "oat-project-review-receive-remote", "oat-project-spec", "oat-project-split", "oat-project-summary", "oat-repo-knowledge-index", "oat-worktree-bootstrap", "oat-worktree-bootstrap-auto", "oat-wrap-up"];
14
+ export declare const WORKFLOW_SKILLS: readonly ["oat-cursor-cloud-projects", "oat-project-autonomous", "oat-project-capture", "oat-project-clear-active", "oat-project-complete", "oat-project-design", "oat-project-dispatch-subagents", "oat-project-discover", "oat-project-document", "oat-project-implement", "oat-project-import-plan", "oat-project-new", "oat-project-next", "oat-project-open", "oat-project-plan", "oat-project-plan-writing", "oat-project-pr-final", "oat-project-pr-progress", "oat-project-progress", "oat-project-promote-spec-driven", "oat-project-quick-start", "oat-project-reconcile", "oat-project-revise", "oat-project-review-provide", "oat-project-review-provide-remote", "oat-project-review-receive", "oat-project-review-receive-remote", "oat-project-spec", "oat-project-split", "oat-project-summary", "oat-repo-knowledge-index", "oat-worktree-bootstrap", "oat-worktree-bootstrap-auto", "oat-wrap-up"];
15
15
  export declare const WORKFLOW_AGENTS: readonly ["oat-codebase-mapper.md", "oat-phase-implementer.md", "oat-reviewer.md"];
16
16
  export declare const WORKFLOW_TEMPLATES: readonly ["state.md", "discovery.md", "spec.md", "design.md", "plan.md", "implementation.md", "summary.md"];
17
17
  export declare const WORKFLOW_SCRIPTS: readonly ["generate-oat-state.sh", "generate-thin-index.sh", "resolve-tracking.sh"];
@@ -1 +1 @@
1
- {"version":3,"file":"skill-manifest.d.ts","sourceRoot":"","sources":["../../../../../src/commands/init/tools/shared/skill-manifest.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAgBH,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,GAAG,SAAS,CAAC;CAClC;AAED,eAAO,MAAM,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAKtD,CAAC;AAEF,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAE5E;AAID,eAAO,MAAM,eAAe,+zBAiClB,CAAC;AAEX,eAAO,MAAM,eAAe,oFAIlB,CAAC;AAEX,eAAO,MAAM,kBAAkB,6GAQrB,CAAC;AAEX,eAAO,MAAM,gBAAgB,qFAInB,CAAC;AAIX,eAAO,MAAM,WAAW,2FAKd,CAAC;AAIX,eAAO,MAAM,WAAW,qCAAsC,CAAC;AAI/D,eAAO,MAAM,WAAW,iLAQd,CAAC;AAEX,eAAO,MAAM,YAAY,kCAAmC,CAAC;AAI7D,eAAO,MAAM,cAAc,2NASjB,CAAC;AAIX,eAAO,MAAM,yBAAyB,sHAK5B,CAAC;AAEX,eAAO,MAAM,4BAA4B,yIAQ/B,CAAC;AAEX,eAAO,MAAM,0BAA0B,aAAc,CAAC;AAItD,eAAO,MAAM,iBAAiB,6BAA8B,CAAC;AAI7D,eAAO,MAAM,eAAe,2EAMlB,CAAC;AAEX,eAAO,MAAM,eAAe,qCAAsC,CAAC"}
1
+ {"version":3,"file":"skill-manifest.d.ts","sourceRoot":"","sources":["../../../../../src/commands/init/tools/shared/skill-manifest.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAgBH,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,GAAG,SAAS,CAAC;CAClC;AAED,eAAO,MAAM,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAKtD,CAAC;AAEF,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAE5E;AAID,eAAO,MAAM,eAAe,s3BAmClB,CAAC;AAEX,eAAO,MAAM,eAAe,oFAIlB,CAAC;AAEX,eAAO,MAAM,kBAAkB,6GAQrB,CAAC;AAEX,eAAO,MAAM,gBAAgB,qFAInB,CAAC;AAIX,eAAO,MAAM,WAAW,2FAKd,CAAC;AAIX,eAAO,MAAM,WAAW,qCAAsC,CAAC;AAI/D,eAAO,MAAM,WAAW,iLAQd,CAAC;AAEX,eAAO,MAAM,YAAY,kCAAmC,CAAC;AAI7D,eAAO,MAAM,cAAc,2NASjB,CAAC;AAIX,eAAO,MAAM,yBAAyB,sHAK5B,CAAC;AAEX,eAAO,MAAM,4BAA4B,yIAQ/B,CAAC;AAEX,eAAO,MAAM,0BAA0B,aAAc,CAAC;AAItD,eAAO,MAAM,iBAAiB,6BAA8B,CAAC;AAI7D,eAAO,MAAM,eAAe,2EAMlB,CAAC;AAEX,eAAO,MAAM,eAAe,qCAAsC,CAAC"}
@@ -16,6 +16,8 @@ export function resolvePackDefaultScope(packName) {
16
16
  }
17
17
  // ── Workflow pack ──────────────────────────────────────────────────
18
18
  export const WORKFLOW_SKILLS = [
19
+ 'oat-cursor-cloud-projects',
20
+ 'oat-project-autonomous',
19
21
  'oat-project-capture',
20
22
  'oat-project-clear-active',
21
23
  'oat-project-complete',
@@ -1,10 +1,11 @@
1
1
  import { type CommandContext, type GlobalOptions } from '../../../../app/command-context.js';
2
2
  import { type PromptContext } from '../../../shared/shared.prompts.js';
3
3
  import { Command } from 'commander';
4
- import { type InstallWorkflowsOptions, type InstallWorkflowsResult } from './install-workflows.js';
4
+ import { type InstallWorkflowsOptions, type InstallWorkflowsResult, type InstallWorkflowsScope } from './install-workflows.js';
5
5
  interface InitToolsWorkflowsDependencies {
6
6
  buildCommandContext: (options: GlobalOptions) => CommandContext;
7
7
  resolveProjectRoot: (cwd: string) => Promise<string>;
8
+ resolveScopeRoot: (scope: InstallWorkflowsScope, cwd: string, home: string) => string;
8
9
  resolveAssetsRoot: () => Promise<string>;
9
10
  installWorkflows: (options: InstallWorkflowsOptions) => Promise<InstallWorkflowsResult>;
10
11
  confirmAction: (message: string, ctx: PromptContext) => Promise<boolean>;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/commands/init/tools/workflows/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,cAAc,EACnB,KAAK,aAAa,EACnB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EAEL,KAAK,aAAa,EACnB,MAAM,iCAAiC,CAAC;AAQzC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAEL,KAAK,uBAAuB,EAC5B,KAAK,sBAAsB,EAC5B,MAAM,qBAAqB,CAAC;AAM7B,UAAU,8BAA8B;IACtC,mBAAmB,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,cAAc,CAAC;IAChE,kBAAkB,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACrD,iBAAiB,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;IACzC,gBAAgB,EAAE,CAChB,OAAO,EAAE,uBAAuB,KAC7B,OAAO,CAAC,sBAAsB,CAAC,CAAC;IACrC,aAAa,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,aAAa,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;CAC1E;AAkGD,wBAAgB,+BAA+B,CAC7C,SAAS,GAAE,OAAO,CAAC,8BAA8B,CAAM,GACtD,OAAO,CAsBT"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/commands/init/tools/workflows/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,cAAc,EACnB,KAAK,aAAa,EACnB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EAEL,KAAK,aAAa,EACnB,MAAM,iCAAiC,CAAC;AAQzC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAEL,KAAK,uBAAuB,EAC5B,KAAK,sBAAsB,EAC3B,KAAK,qBAAqB,EAC3B,MAAM,qBAAqB,CAAC;AAM7B,UAAU,8BAA8B;IACtC,mBAAmB,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,cAAc,CAAC;IAChE,kBAAkB,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACrD,gBAAgB,EAAE,CAChB,KAAK,EAAE,qBAAqB,EAC5B,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,MAAM,KACT,MAAM,CAAC;IACZ,iBAAiB,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;IACzC,gBAAgB,EAAE,CAChB,OAAO,EAAE,uBAAuB,KAC7B,OAAO,CAAC,sBAAsB,CAAC,CAAC;IACrC,aAAa,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,aAAa,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;CAC1E;AAoGD,wBAAgB,+BAA+B,CAC7C,SAAS,GAAE,OAAO,CAAC,8BAA8B,CAAM,GACtD,OAAO,CAsBT"}
@@ -4,22 +4,22 @@ import { confirmAction, } from '../../../shared/shared.prompts.js';
4
4
  import { readGlobalOptions } from '../../../shared/shared.utils.js';
5
5
  import { canonicalPathsForPack, setInstalledCanonicalPaths, } from '../../../tools/shared/install-sync-context.js';
6
6
  import { resolveAssetsRoot } from '../../../../fs/assets.js';
7
- import { resolveProjectRoot } from '../../../../fs/paths.js';
7
+ import { resolveProjectRoot, resolveScopeRoot } from '../../../../fs/paths.js';
8
8
  import { Command } from 'commander';
9
9
  import { installWorkflows as defaultInstallWorkflows, } from './install-workflows.js';
10
- const PROJECT_SCOPE_ONLY_MESSAGE = 'oat init tools workflows currently supports only --scope project.';
11
10
  const DEFAULT_DEPENDENCIES = {
12
11
  buildCommandContext,
13
12
  resolveProjectRoot,
13
+ resolveScopeRoot,
14
14
  resolveAssetsRoot,
15
15
  installWorkflows: defaultInstallWorkflows,
16
16
  confirmAction,
17
17
  };
18
- function reportSuccess(context, targetRoot, assetsRoot, result) {
18
+ function reportSuccess(context, scope, targetRoot, assetsRoot, result) {
19
19
  if (context.json) {
20
20
  context.logger.json({
21
21
  status: 'ok',
22
- scope: 'project',
22
+ scope,
23
23
  targetRoot,
24
24
  assetsRoot,
25
25
  result,
@@ -27,22 +27,23 @@ function reportSuccess(context, targetRoot, assetsRoot, result) {
27
27
  return;
28
28
  }
29
29
  context.logger.info('Installed workflows tool pack.');
30
+ context.logger.info(`Scope: ${scope}`);
30
31
  context.logger.info(`Target root: ${targetRoot}`);
31
32
  context.logger.info(`Skills: copied=${result.copiedSkills.length}, updated=${result.updatedSkills.length}, skipped=${result.skippedSkills.length}`);
32
33
  context.logger.info(`Agents: copied=${result.copiedAgents.length}, updated=${result.updatedAgents.length}, skipped=${result.skippedAgents.length}`);
33
34
  context.logger.info(`Templates: copied=${result.copiedTemplates.length}, updated=${result.updatedTemplates.length}, skipped=${result.skippedTemplates.length}`);
34
35
  context.logger.info(`Scripts: copied=${result.copiedScripts.length}, updated=${result.updatedScripts.length}, skipped=${result.skippedScripts.length}`);
35
36
  context.logger.info(`Projects root initialized: ${result.projectsRootInitialized ? 'yes' : 'no'}`);
36
- context.logger.info('Run: oat sync --scope project');
37
+ context.logger.info(`Run: oat sync --scope ${scope}`);
37
38
  }
38
39
  async function runInitToolsWorkflows(context, options, dependencies) {
39
40
  try {
40
- if (context.scope === 'user') {
41
- throw new Error(PROJECT_SCOPE_ONLY_MESSAGE);
42
- }
43
- const targetRoot = await dependencies.resolveProjectRoot(context.cwd);
41
+ const scope = context.scope === 'user' ? 'user' : 'project';
42
+ const targetRoot = scope === 'user'
43
+ ? dependencies.resolveScopeRoot('user', context.cwd, context.home)
44
+ : await dependencies.resolveProjectRoot(context.cwd);
44
45
  if (options.force && context.interactive) {
45
- const confirmed = await dependencies.confirmAction('Force overwrite existing workflows assets in project scope?', { interactive: context.interactive });
46
+ const confirmed = await dependencies.confirmAction(`Force overwrite existing workflows assets in ${scope} scope?`, { interactive: context.interactive });
46
47
  if (!confirmed) {
47
48
  if (!context.json) {
48
49
  context.logger.info('Cancelled: no files were overwritten.');
@@ -55,9 +56,10 @@ async function runInitToolsWorkflows(context, options, dependencies) {
55
56
  const result = await dependencies.installWorkflows({
56
57
  assetsRoot,
57
58
  targetRoot,
59
+ scope,
58
60
  force: options.force,
59
61
  });
60
- reportSuccess(context, targetRoot, assetsRoot, result);
62
+ reportSuccess(context, scope, targetRoot, assetsRoot, result);
61
63
  process.exitCode = 0;
62
64
  return true;
63
65
  }
@@ -1,8 +1,10 @@
1
1
  import { WORKFLOW_AGENTS, WORKFLOW_SCRIPTS, WORKFLOW_SKILLS, WORKFLOW_TEMPLATES } from '../../../init/tools/shared/skill-manifest.js';
2
+ export type InstallWorkflowsScope = 'project' | 'user';
2
3
  export { WORKFLOW_AGENTS, WORKFLOW_SCRIPTS, WORKFLOW_SKILLS, WORKFLOW_TEMPLATES, };
3
4
  export interface InstallWorkflowsOptions {
4
5
  assetsRoot: string;
5
6
  targetRoot: string;
7
+ scope?: InstallWorkflowsScope;
6
8
  force?: boolean;
7
9
  }
8
10
  export interface InstallWorkflowsResult {
@@ -1 +1 @@
1
- {"version":3,"file":"install-workflows.d.ts","sourceRoot":"","sources":["../../../../../src/commands/init/tools/workflows/install-workflows.ts"],"names":[],"mappings":"AAOA,OAAO,EACL,eAAe,EACf,gBAAgB,EAChB,eAAe,EACf,kBAAkB,EACnB,MAAM,4CAA4C,CAAC;AAIpD,OAAO,EACL,eAAe,EACf,gBAAgB,EAChB,eAAe,EACf,kBAAkB,GACnB,CAAC;AAEF,MAAM,WAAW,uBAAuB;IACtC,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,sBAAsB;IACrC,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,cAAc,EAAE,KAAK,CAAC;QACpB,IAAI,EAAE,MAAM,CAAC;QACb,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;QACzB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;KACxB,CAAC,CAAC;IACH,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,uBAAuB,EAAE,OAAO,CAAC;IACjC,6BAA6B,EAAE,OAAO,CAAC;IACvC,sBAAsB,EAAE,OAAO,CAAC;IAChC,oBAAoB,EAAE,MAAM,CAAC;CAC9B;AAED,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,uBAAuB,GAC/B,OAAO,CAAC,sBAAsB,CAAC,CA0IjC"}
1
+ {"version":3,"file":"install-workflows.d.ts","sourceRoot":"","sources":["../../../../../src/commands/init/tools/workflows/install-workflows.ts"],"names":[],"mappings":"AAOA,OAAO,EACL,eAAe,EACf,gBAAgB,EAChB,eAAe,EACf,kBAAkB,EACnB,MAAM,4CAA4C,CAAC;AAIpD,MAAM,MAAM,qBAAqB,GAAG,SAAS,GAAG,MAAM,CAAC;AAEvD,OAAO,EACL,eAAe,EACf,gBAAgB,EAChB,eAAe,EACf,kBAAkB,GACnB,CAAC;AAEF,MAAM,WAAW,uBAAuB;IACtC,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,qBAAqB,CAAC;IAC9B,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,sBAAsB;IACrC,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,cAAc,EAAE,KAAK,CAAC;QACpB,IAAI,EAAE,MAAM,CAAC;QACb,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;QACzB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;KACxB,CAAC,CAAC;IACH,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,uBAAuB,EAAE,OAAO,CAAC;IACjC,6BAA6B,EAAE,OAAO,CAAC;IACvC,sBAAsB,EAAE,OAAO,CAAC;IAChC,oBAAoB,EAAE,MAAM,CAAC;CAC9B;AAED,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,uBAAuB,GAC/B,OAAO,CAAC,sBAAsB,CAAC,CA+IjC"}
@@ -7,6 +7,7 @@ import { dirExists, ensureDir, fileExists } from '../../../../fs/io.js';
7
7
  export { WORKFLOW_AGENTS, WORKFLOW_SCRIPTS, WORKFLOW_SKILLS, WORKFLOW_TEMPLATES, };
8
8
  export async function installWorkflows(options) {
9
9
  const force = options.force ?? false;
10
+ const scope = options.scope ?? 'project';
10
11
  const result = {
11
12
  copiedSkills: [],
12
13
  updatedSkills: [],
@@ -97,6 +98,9 @@ export async function installWorkflows(options) {
97
98
  result.skippedScripts.push(script);
98
99
  }
99
100
  }
101
+ if (scope === 'user') {
102
+ return result;
103
+ }
100
104
  const projectsRootPath = join(options.targetRoot, '.oat', 'projects-root');
101
105
  const hasProjectsRoot = await fileExists(projectsRootPath);
102
106
  if (!hasProjectsRoot) {
@@ -14,6 +14,7 @@ export interface ScaffoldProjectOptions {
14
14
  */
15
15
  commit?: boolean;
16
16
  env?: NodeJS.ProcessEnv;
17
+ home?: string;
17
18
  today?: string;
18
19
  nowUtc?: string;
19
20
  refreshDashboardCallback?: (repoRoot: string) => void | Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"scaffold.d.ts","sourceRoot":"","sources":["../../../../src/commands/project/new/scaffold.ts"],"names":[],"mappings":"AAUA,MAAM,MAAM,mBAAmB,GAAG,aAAa,GAAG,OAAO,GAAG,QAAQ,CAAC;AAErE,MAAM,WAAW,sBAAsB;IACrC,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,mBAAmB,CAAC;IAC3B,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B;;;;;OAKG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,wBAAwB,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACvE;AAED;;;;GAIG;AACH,MAAM,MAAM,oBAAoB,GAC5B,WAAW,GACX,kBAAkB,GAClB,qBAAqB,GACrB,iBAAiB,GACjB,QAAQ,CAAC;AAEb,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,mBAAmB,CAAC;IAC1B,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,oBAAoB,EAAE,OAAO,CAAC;IAC9B,kBAAkB,EAAE,OAAO,CAAC;IAC5B,SAAS,EAAE,OAAO,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,oBAAoB,CAAC;IACnC,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAoRD,wBAAsB,eAAe,CACnC,OAAO,EAAE,sBAAsB,GAC9B,OAAO,CAAC,qBAAqB,CAAC,CA4EhC"}
1
+ {"version":3,"file":"scaffold.d.ts","sourceRoot":"","sources":["../../../../src/commands/project/new/scaffold.ts"],"names":[],"mappings":"AAYA,MAAM,MAAM,mBAAmB,GAAG,aAAa,GAAG,OAAO,GAAG,QAAQ,CAAC;AAErE,MAAM,WAAW,sBAAsB;IACrC,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,mBAAmB,CAAC;IAC3B,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B;;;;;OAKG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,wBAAwB,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACvE;AAED;;;;GAIG;AACH,MAAM,MAAM,oBAAoB,GAC5B,WAAW,GACX,kBAAkB,GAClB,qBAAqB,GACrB,iBAAiB,GACjB,QAAQ,CAAC;AAEb,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,mBAAmB,CAAC;IAC1B,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,oBAAoB,EAAE,OAAO,CAAC;IAC9B,kBAAkB,EAAE,OAAO,CAAC;IAC5B,SAAS,EAAE,OAAO,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,oBAAoB,CAAC;IACnC,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AA2SD,wBAAsB,eAAe,CACnC,OAAO,EAAE,sBAAsB,GAC9B,OAAO,CAAC,qBAAqB,CAAC,CAoFhC"}
@@ -1,9 +1,11 @@
1
1
  import { execFileSync } from 'node:child_process';
2
2
  import { mkdir, readFile, writeFile } from 'node:fs/promises';
3
+ import { homedir } from 'node:os';
3
4
  import { join } from 'node:path';
4
5
  import { resolveProjectsRoot } from '../../shared/oat-paths.js';
5
6
  import { generateStateDashboard } from '../../state/generate.js';
6
7
  import { setActiveProject } from '../../../config/oat-config.js';
8
+ import { resolveAssetsRoot } from '../../../fs/assets.js';
7
9
  import { fileExists } from '../../../fs/io.js';
8
10
  import { assertValidProjectStateContent } from '../../../validation/project-state.js';
9
11
  const TEMPLATES_BY_MODE = {
@@ -162,12 +164,11 @@ function commitScaffold(cwd, projectPath, projectName, createdFiles) {
162
164
  return { status: 'failed', committed: false, error: message };
163
165
  }
164
166
  }
165
- async function scaffoldModeTemplates(repoRoot, projectPath, projectName, mode, today, nowUtc) {
166
- const templatesDir = join(repoRoot, '.oat', 'templates');
167
+ async function scaffoldModeTemplates(userOatRoot, repoRoot, projectPath, projectName, mode, today, nowUtc) {
167
168
  const createdFiles = [];
168
169
  const skippedFiles = [];
169
170
  for (const templateFile of TEMPLATES_BY_MODE[mode]) {
170
- const src = join(templatesDir, templateFile);
171
+ const src = await resolveTemplateSource(userOatRoot, repoRoot, templateFile);
171
172
  const dest = join(repoRoot, projectPath, templateFile);
172
173
  if (await fileExists(dest)) {
173
174
  skippedFiles.push(templateFile);
@@ -183,6 +184,18 @@ async function scaffoldModeTemplates(repoRoot, projectPath, projectName, mode, t
183
184
  }
184
185
  return { createdFiles, skippedFiles };
185
186
  }
187
+ async function resolveTemplateSource(userOatRoot, repoRoot, templateFile) {
188
+ const userSource = join(userOatRoot, 'templates', templateFile);
189
+ if (await fileExists(userSource)) {
190
+ return userSource;
191
+ }
192
+ const repoSource = join(repoRoot, '.oat', 'templates', templateFile);
193
+ if (await fileExists(repoSource)) {
194
+ return repoSource;
195
+ }
196
+ const assetsRoot = await resolveAssetsRoot();
197
+ return join(assetsRoot, 'templates', templateFile);
198
+ }
186
199
  async function ensureStructure(repoRoot, projectPath, mode) {
187
200
  const projectRoot = join(repoRoot, projectPath);
188
201
  await mkdir(projectRoot, { recursive: true });
@@ -202,6 +215,12 @@ export async function scaffoldProject(options) {
202
215
  const setActive = options.setActive ?? true;
203
216
  const refreshDashboard = options.refreshDashboard ?? true;
204
217
  const env = options.env ?? process.env;
218
+ const home = options.home ??
219
+ env.HOME ??
220
+ env.USERPROFILE ??
221
+ process.env.HOME ??
222
+ homedir();
223
+ const userOatRoot = join(home, '.oat');
205
224
  const now = new Date();
206
225
  const today = options.today ?? now.toISOString().slice(0, 10);
207
226
  const nowUtc = options.nowUtc ?? now.toISOString();
@@ -212,7 +231,7 @@ export async function scaffoldProject(options) {
212
231
  // Scaffold behavior is always non-destructive (create missing files only).
213
232
  void options.force;
214
233
  await ensureStructure(options.repoRoot, projectPath, mode);
215
- const { createdFiles, skippedFiles } = await scaffoldModeTemplates(options.repoRoot, projectPath, options.projectName, mode, today, nowUtc);
234
+ const { createdFiles, skippedFiles } = await scaffoldModeTemplates(userOatRoot, options.repoRoot, projectPath, options.projectName, mode, today, nowUtc);
216
235
  if (setActive) {
217
236
  await setActiveProject(options.repoRoot, projectPath);
218
237
  }
@@ -1,5 +1,5 @@
1
1
  import { execFile } from 'node:child_process';
2
- import { rm, unlink } from 'node:fs/promises';
2
+ import { rm } from 'node:fs/promises';
3
3
  import { buildCommandContext } from '../../../app/command-context.js';
4
4
  import { withScopeOption } from '../../shared/scope-option.js';
5
5
  import { readGlobalOptions, resolveConcreteScopes, } from '../../shared/shared.utils.js';
@@ -22,7 +22,7 @@ const defaultDependencies = {
22
22
  await rm(path, { recursive: true, force: true });
23
23
  },
24
24
  removeFile: async (path) => {
25
- await unlink(path);
25
+ await rm(path, { force: true });
26
26
  },
27
27
  };
28
28
  const defaultSyncDependencies = {
@@ -1 +1 @@
1
- {"version":3,"file":"remove-tools.d.ts","sourceRoot":"","sources":["../../../../src/commands/tools/remove/remove-tools.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AAC1E,OAAO,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,8BAA8B,CAAC;AACvE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAEnD,MAAM,MAAM,YAAY,GACpB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAC9B;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,QAAQ,CAAA;CAAE,GAChC;IAAE,IAAI,EAAE,KAAK,CAAA;CAAE,CAAC;AAEpB,MAAM,WAAW,uBAAuB;IACtC,SAAS,EAAE,CAAC,OAAO,EAAE,gBAAgB,KAAK,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC;IAC9D,gBAAgB,EAAE,CAChB,KAAK,EAAE,aAAa,EACpB,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,MAAM,KACT,OAAO,CAAC,MAAM,CAAC,CAAC;IACrB,iBAAiB,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;IACzC,eAAe,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACjD,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAC7C;AAED,UAAU,WAAW;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC;IACxB,KAAK,EAAE,aAAa,CAAC;CACtB;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,WAAW,EAAE,CAAC;IACvB,YAAY,EAAE,MAAM,EAAE,CAAC;CACxB;AA8BD,wBAAsB,WAAW,CAC/B,MAAM,EAAE,YAAY,EACpB,MAAM,EAAE,aAAa,EAAE,EACvB,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,OAAO,EACf,IAAI,EAAE,uBAAuB,GAC5B,OAAO,CAAC,YAAY,CAAC,CAqBvB"}
1
+ {"version":3,"file":"remove-tools.d.ts","sourceRoot":"","sources":["../../../../src/commands/tools/remove/remove-tools.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AAC1E,OAAO,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,8BAA8B,CAAC;AACvE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAEnD,MAAM,MAAM,YAAY,GACpB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAC9B;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,QAAQ,CAAA;CAAE,GAChC;IAAE,IAAI,EAAE,KAAK,CAAA;CAAE,CAAC;AAEpB,MAAM,WAAW,uBAAuB;IACtC,SAAS,EAAE,CAAC,OAAO,EAAE,gBAAgB,KAAK,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC;IAC9D,gBAAgB,EAAE,CAChB,KAAK,EAAE,aAAa,EACpB,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,MAAM,KACT,OAAO,CAAC,MAAM,CAAC,CAAC;IACrB,iBAAiB,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;IACzC,eAAe,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACjD,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAC7C;AAED,UAAU,WAAW;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC;IACxB,KAAK,EAAE,aAAa,CAAC;CACtB;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,WAAW,EAAE,CAAC;IACvB,YAAY,EAAE,MAAM,EAAE,CAAC;CACxB;AAqDD,wBAAsB,WAAW,CAC/B,MAAM,EAAE,YAAY,EACpB,MAAM,EAAE,aAAa,EAAE,EACvB,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,OAAO,EACf,IAAI,EAAE,uBAAuB,GAC5B,OAAO,CAAC,YAAY,CAAC,CAgCvB"}
@@ -1,4 +1,5 @@
1
1
  import { join } from 'node:path';
2
+ import { WORKFLOW_AGENTS, WORKFLOW_SCRIPTS, WORKFLOW_TEMPLATES, } from '../../init/tools/shared/skill-manifest.js';
2
3
  function matchesTarget(tool, target) {
3
4
  switch (target.kind) {
4
5
  case 'name':
@@ -21,6 +22,20 @@ async function removeTool(tool, scopeRoot, dryRun, deps) {
21
22
  await deps.removeDirectory(skillPath);
22
23
  }
23
24
  }
25
+ async function removePackCompanionAssets(pack, scope, scopeRoot, dryRun, deps) {
26
+ if (dryRun || pack !== 'workflows' || scope !== 'user') {
27
+ return;
28
+ }
29
+ for (const agent of WORKFLOW_AGENTS) {
30
+ await deps.removeFile(join(scopeRoot, '.agents', 'agents', agent));
31
+ }
32
+ for (const template of WORKFLOW_TEMPLATES) {
33
+ await deps.removeFile(join(scopeRoot, '.oat', 'templates', template));
34
+ }
35
+ for (const script of WORKFLOW_SCRIPTS) {
36
+ await deps.removeFile(join(scopeRoot, '.oat', 'scripts', script));
37
+ }
38
+ }
24
39
  export async function removeTools(target, scopes, cwd, home, dryRun, deps) {
25
40
  const removed = [];
26
41
  const assetsRoot = await deps.resolveAssetsRoot();
@@ -32,6 +47,14 @@ export async function removeTools(target, scopes, cwd, home, dryRun, deps) {
32
47
  await removeTool(tool, scopeRoot, dryRun, deps);
33
48
  removed.push({ name: tool.name, type: tool.type, scope: tool.scope });
34
49
  }
50
+ if (target.kind !== 'name') {
51
+ const matchedPacks = new Set(matched
52
+ .map((tool) => tool.pack)
53
+ .filter((pack) => pack !== 'custom'));
54
+ for (const pack of matchedPacks) {
55
+ await removePackCompanionAssets(pack, scope, scopeRoot, dryRun, deps);
56
+ }
57
+ }
35
58
  }
36
59
  const notInstalled = [];
37
60
  if (target.kind === 'name' && removed.length === 0) {
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/commands/tools/update/index.ts"],"names":[],"mappings":"AAcA,OAAO,EACL,KAAK,oBAAoB,EAE1B,MAAM,kCAAkC,CAAC;AAE1C,OAAO,KAAK,EAAY,QAAQ,EAAE,MAAM,8BAA8B,CAAC;AAKvE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EACL,KAAK,YAAY,EACjB,KAAK,YAAY,EACjB,KAAK,uBAAuB,EAE7B,MAAM,gBAAgB,CAAC;AAexB,wBAAgB,uBAAuB,CACrC,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,EAAE,EAClB,OAAO,EAAE;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,SAAS,GAAG,MAAM,CAAA;CAAE,GAClD,MAAM,EAAE,CAaV;AAgCD,wBAAgB,wBAAwB,CACtC,YAAY,GAAE,uBAA6C,EAC3D,gBAAgB,GAAE,oBAA8C,GAC/D,OAAO,CA4JT;AAED;;;;GAIG;AACH,wBAAgB,+BAA+B,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAI7E;AAED,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,YAAY,EACpB,MAAM,EAAE,YAAY,GACnB,OAAO,CAOT;AAED,wBAAgB,wBAAwB,CACtC,IAAI,EAAE,QAAQ,EACd,MAAM,EAAE,OAAO,GACd,MAAM,CAMR"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/commands/tools/update/index.ts"],"names":[],"mappings":"AAeA,OAAO,EACL,KAAK,oBAAoB,EAE1B,MAAM,kCAAkC,CAAC;AAE1C,OAAO,KAAK,EAAY,QAAQ,EAAE,MAAM,8BAA8B,CAAC;AAKvE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EACL,KAAK,YAAY,EACjB,KAAK,YAAY,EACjB,KAAK,uBAAuB,EAE7B,MAAM,gBAAgB,CAAC;AAgBxB,wBAAgB,uBAAuB,CACrC,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,EAAE,EAClB,OAAO,EAAE;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,SAAS,GAAG,MAAM,CAAA;CAAE,GAClD,MAAM,EAAE,CAaV;AAgCD,wBAAgB,wBAAwB,CACtC,YAAY,GAAE,uBAA6C,EAC3D,gBAAgB,GAAE,oBAA8C,GAC/D,OAAO,CAoKT;AAED;;;;GAIG;AACH,wBAAgB,+BAA+B,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAI7E;AAED,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,YAAY,EACpB,MAAM,EAAE,YAAY,GACnB,OAAO,CAOT;AAED,wBAAgB,wBAAwB,CACtC,IAAI,EAAE,QAAQ,EACd,MAAM,EAAE,OAAO,GACd,MAAM,CAMR"}
@@ -1,4 +1,5 @@
1
1
  import { execFile } from 'node:child_process';
2
+ import { chmod } from 'node:fs/promises';
2
3
  import { join } from 'node:path';
3
4
  import { buildCommandContext } from '../../../app/command-context.js';
4
5
  import { applyOatCoreGitignore } from '../../init/gitignore.js';
@@ -24,6 +25,7 @@ const defaultDependencies = {
24
25
  copyDirWithStatus,
25
26
  copyFileWithStatus,
26
27
  fileExists,
28
+ chmod,
27
29
  applyOatCoreGitignore,
28
30
  };
29
31
  export function buildSyncSubprocessArgs(entrypoint, execArgv, options) {
@@ -166,7 +168,11 @@ export function createToolsUpdateCommand(dependencies = defaultDependencies, syn
166
168
  for (const tool of result.notBundled) {
167
169
  logger.info(`Not bundled (custom): ${tool.name}`);
168
170
  }
169
- if (result.updated.length === 0) {
171
+ for (const asset of result.assetRefreshes) {
172
+ const action = asset.status === 'planned' ? 'Would refresh' : 'Refreshed';
173
+ logger.info(`${action} ${asset.type}: ${asset.name} (${asset.scope} ${asset.pack} pack)`);
174
+ }
175
+ if (result.updated.length === 0 && result.assetRefreshes.length === 0) {
170
176
  logger.info('No tools to update.');
171
177
  }
172
178
  });
@@ -12,12 +12,20 @@ export type UpdateTarget = {
12
12
  } | {
13
13
  kind: 'all';
14
14
  };
15
+ export interface PackAssetRefresh {
16
+ name: string;
17
+ type: 'template' | 'script';
18
+ pack: PackName;
19
+ scope: ConcreteScope;
20
+ status: 'planned' | 'refreshed';
21
+ }
15
22
  export interface UpdateResult {
16
23
  updated: ToolInfo[];
17
24
  current: ToolInfo[];
18
25
  newer: ToolInfo[];
19
26
  notInstalled: string[];
20
27
  notBundled: ToolInfo[];
28
+ assetRefreshes: PackAssetRefresh[];
21
29
  }
22
30
  export interface UpdateToolsDependencies {
23
31
  scanTools: (options: ScanToolsOptions) => Promise<ToolInfo[]>;
@@ -26,6 +34,7 @@ export interface UpdateToolsDependencies {
26
34
  copyDirWithStatus: (source: string, destination: string, force: boolean) => Promise<CopyStatus>;
27
35
  copyFileWithStatus: (source: string, destination: string, force: boolean) => Promise<CopyStatus>;
28
36
  fileExists: (path: string) => Promise<boolean>;
37
+ chmod: (path: string, mode: number) => Promise<void>;
29
38
  applyOatCoreGitignore?: (repoRoot: string) => Promise<ApplyOatCoreResult>;
30
39
  }
31
40
  export declare function updateTools(target: UpdateTarget, scopes: ConcreteScope[], cwd: string, home: string, dryRun: boolean, dependencies: UpdateToolsDependencies): Promise<UpdateResult>;
@@ -1 +1 @@
1
- {"version":3,"file":"update-tools.d.ts","sourceRoot":"","sources":["../../../../src/commands/tools/update/update-tools.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AACnE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,0CAA0C,CAAC;AAkB3E,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AAC1E,OAAO,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,8BAA8B,CAAC;AACvE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAEnD,MAAM,MAAM,YAAY,GACpB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAC9B;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,QAAQ,CAAA;CAAE,GAChC;IAAE,IAAI,EAAE,KAAK,CAAA;CAAE,CAAC;AAEpB,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,QAAQ,EAAE,CAAC;IACpB,OAAO,EAAE,QAAQ,EAAE,CAAC;IACpB,KAAK,EAAE,QAAQ,EAAE,CAAC;IAClB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,UAAU,EAAE,QAAQ,EAAE,CAAC;CACxB;AAED,MAAM,WAAW,uBAAuB;IACtC,SAAS,EAAE,CAAC,OAAO,EAAE,gBAAgB,KAAK,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC;IAC9D,gBAAgB,EAAE,CAChB,KAAK,EAAE,aAAa,EACpB,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,MAAM,KACT,OAAO,CAAC,MAAM,CAAC,CAAC;IACrB,iBAAiB,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;IACzC,iBAAiB,EAAE,CACjB,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,OAAO,KACX,OAAO,CAAC,UAAU,CAAC,CAAC;IACzB,kBAAkB,EAAE,CAClB,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,OAAO,KACX,OAAO,CAAC,UAAU,CAAC,CAAC;IACzB,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAC/C,qBAAqB,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,kBAAkB,CAAC,CAAC;CAC3E;AAmFD,wBAAsB,WAAW,CAC/B,MAAM,EAAE,YAAY,EACpB,MAAM,EAAE,aAAa,EAAE,EACvB,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,OAAO,EACf,YAAY,EAAE,uBAAuB,GACpC,OAAO,CAAC,YAAY,CAAC,CA0GvB"}
1
+ {"version":3,"file":"update-tools.d.ts","sourceRoot":"","sources":["../../../../src/commands/tools/update/update-tools.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AACnE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,0CAA0C,CAAC;AAkB3E,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AAC1E,OAAO,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,8BAA8B,CAAC;AACvE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAEnD,MAAM,MAAM,YAAY,GACpB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAC9B;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,QAAQ,CAAA;CAAE,GAChC;IAAE,IAAI,EAAE,KAAK,CAAA;CAAE,CAAC;AAEpB,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,UAAU,GAAG,QAAQ,CAAC;IAC5B,IAAI,EAAE,QAAQ,CAAC;IACf,KAAK,EAAE,aAAa,CAAC;IACrB,MAAM,EAAE,SAAS,GAAG,WAAW,CAAC;CACjC;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,QAAQ,EAAE,CAAC;IACpB,OAAO,EAAE,QAAQ,EAAE,CAAC;IACpB,KAAK,EAAE,QAAQ,EAAE,CAAC;IAClB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,UAAU,EAAE,QAAQ,EAAE,CAAC;IACvB,cAAc,EAAE,gBAAgB,EAAE,CAAC;CACpC;AAED,MAAM,WAAW,uBAAuB;IACtC,SAAS,EAAE,CAAC,OAAO,EAAE,gBAAgB,KAAK,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC;IAC9D,gBAAgB,EAAE,CAChB,KAAK,EAAE,aAAa,EACpB,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,MAAM,KACT,OAAO,CAAC,MAAM,CAAC,CAAC;IACrB,iBAAiB,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;IACzC,iBAAiB,EAAE,CACjB,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,OAAO,KACX,OAAO,CAAC,UAAU,CAAC,CAAC;IACzB,kBAAkB,EAAE,CAClB,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,OAAO,KACX,OAAO,CAAC,UAAU,CAAC,CAAC;IACzB,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAC/C,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACrD,qBAAqB,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,kBAAkB,CAAC,CAAC;CAC3E;AAoFD,wBAAsB,WAAW,CAC/B,MAAM,EAAE,YAAY,EACpB,MAAM,EAAE,aAAa,EAAE,EACvB,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,OAAO,EACf,YAAY,EAAE,uBAAuB,GACpC,OAAO,CAAC,YAAY,CAAC,CA8HvB"}
@@ -67,6 +67,7 @@ export async function updateTools(target, scopes, cwd, home, dryRun, dependencie
67
67
  newer: [],
68
68
  notInstalled: [],
69
69
  notBundled: [],
70
+ assetRefreshes: [],
70
71
  };
71
72
  const allTools = [];
72
73
  for (const scope of scopes) {
@@ -126,7 +127,16 @@ export async function updateTools(target, scopes, cwd, home, dryRun, dependencie
126
127
  for (const template of assets.templates) {
127
128
  const source = join(assetsRoot, 'templates', template);
128
129
  const destination = join(assetTarget.scopeRoot, '.oat', 'templates', template);
129
- await dependencies.copyFileWithStatus(source, destination, true);
130
+ if (!dryRun) {
131
+ await dependencies.copyFileWithStatus(source, destination, true);
132
+ }
133
+ result.assetRefreshes.push({
134
+ name: template,
135
+ type: 'template',
136
+ pack: assetTarget.pack,
137
+ scope: assetTarget.scope,
138
+ status: dryRun ? 'planned' : 'refreshed',
139
+ });
130
140
  }
131
141
  for (const script of assets.scripts) {
132
142
  const source = join(assetsRoot, 'scripts', script);
@@ -134,7 +144,17 @@ export async function updateTools(target, scopes, cwd, home, dryRun, dependencie
134
144
  continue;
135
145
  }
136
146
  const destination = join(assetTarget.scopeRoot, '.oat', 'scripts', script);
137
- await dependencies.copyFileWithStatus(source, destination, true);
147
+ if (!dryRun) {
148
+ await dependencies.copyFileWithStatus(source, destination, true);
149
+ await dependencies.chmod(destination, 0o755);
150
+ }
151
+ result.assetRefreshes.push({
152
+ name: script,
153
+ type: 'script',
154
+ pack: assetTarget.pack,
155
+ scope: assetTarget.scope,
156
+ status: dryRun ? 'planned' : 'refreshed',
157
+ });
138
158
  }
139
159
  }
140
160
  return result;
@@ -182,7 +202,7 @@ function expandInstalledPackEntries(target, installedEntries) {
182
202
  return entries;
183
203
  }
184
204
  function getBundledPackMembers(pack, scope) {
185
- return BUNDLED_PACK_MEMBERS[pack].filter((member) => scope === 'project' || member.type === 'skill');
205
+ return BUNDLED_PACK_MEMBERS[pack].filter((member) => scope === 'project' || member.type === 'skill' || pack === 'workflows');
186
206
  }
187
207
  function resolvePackAssetTargets(target, installedEntries) {
188
208
  if (target.kind === 'name') {
@@ -195,7 +215,7 @@ function resolvePackAssetTargets(target, installedEntries) {
195
215
  entriesByScope.set(entry.tool.scope, scopeEntries);
196
216
  }
197
217
  const targets = [];
198
- for (const scopeEntries of entriesByScope.values()) {
218
+ for (const [scope, scopeEntries] of entriesByScope) {
199
219
  const scopeRoot = scopeEntries[0]?.scopeRoot;
200
220
  if (!scopeRoot)
201
221
  continue;
@@ -212,7 +232,7 @@ function resolvePackAssetTargets(target, installedEntries) {
212
232
  if (assets.templates.length === 0 && assets.scripts.length === 0) {
213
233
  continue;
214
234
  }
215
- targets.push({ pack, scopeRoot });
235
+ targets.push({ pack, scope, scopeRoot });
216
236
  }
217
237
  }
218
238
  return targets;
@@ -1,4 +1,4 @@
1
- export type ModelFamily = 'claude' | 'openai' | 'composer' | 'glm' | 'unknown';
1
+ export type ModelFamily = 'claude' | 'openai' | 'xai' | 'composer' | 'glm' | 'unknown';
2
2
  interface ClassifyModelFamilyInput {
3
3
  value: string;
4
4
  /**