@open-agent-toolkit/cli 0.1.73 → 0.1.74

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 (90) hide show
  1. package/assets/config/dispatch-matrix-recommendation.json +13 -17
  2. package/assets/docs/cli-utilities/configuration.md +35 -60
  3. package/assets/docs/cli-utilities/workflow-gates.md +38 -2
  4. package/assets/docs/provider-sync/providers.md +15 -17
  5. package/assets/docs/workflows/projects/artifacts.md +1 -1
  6. package/assets/docs/workflows/projects/dispatch-ceiling.md +29 -33
  7. package/assets/docs/workflows/projects/implementation-execution.md +7 -4
  8. package/assets/docs/workflows/projects/lifecycle.md +4 -3
  9. package/assets/public-package-versions.json +4 -4
  10. package/assets/skills/oat-dispatch-subagents/SKILL.md +1 -1
  11. package/assets/skills/oat-dispatch-subagents/references/provider-cursor.md +27 -15
  12. package/assets/skills/oat-project-autonomous/SKILL.md +1 -1
  13. package/assets/skills/oat-project-autonomous/references/gate-inventory.md +1 -1
  14. package/assets/skills/oat-project-document/references/docs/autonomy-contract.md +1 -1
  15. package/assets/skills/oat-project-implement/references/completion-and-closeout.md +17 -15
  16. package/assets/skills/oat-project-implement/references/dispatch-and-dry-run.md +15 -9
  17. package/assets/skills/oat-project-implement/references/docs/autonomy-contract.md +1 -1
  18. package/assets/skills/oat-project-implement/references/phase-execution.md +11 -5
  19. package/assets/skills/oat-project-import-plan/SKILL.md +30 -8
  20. package/assets/skills/oat-project-plan/SKILL.md +30 -8
  21. package/assets/skills/oat-project-plan-writing/SKILL.md +12 -9
  22. package/assets/skills/oat-project-pr-final/references/docs/autonomy-contract.md +1 -1
  23. package/assets/skills/oat-project-quick-start/SKILL.md +30 -8
  24. package/assets/skills/oat-project-quick-start/references/docs/autonomy-contract.md +1 -1
  25. package/assets/skills/oat-project-review-provide/SKILL.md +19 -11
  26. package/assets/skills/oat-project-review-provide-remote/SKILL.md +27 -4
  27. package/dist/commands/doctor/index.d.ts +2 -1
  28. package/dist/commands/doctor/index.d.ts.map +1 -1
  29. package/dist/commands/doctor/index.js +37 -1
  30. package/dist/commands/gate/index.d.ts +1 -1
  31. package/dist/commands/gate/index.d.ts.map +1 -1
  32. package/dist/commands/gate/index.js +35 -3
  33. package/dist/commands/init/index.d.ts +1 -1
  34. package/dist/commands/init/index.d.ts.map +1 -1
  35. package/dist/commands/init/index.js +40 -8
  36. package/dist/commands/project/dispatch-ceiling/index.d.ts.map +1 -1
  37. package/dist/commands/project/dispatch-ceiling/index.js +17 -9
  38. package/dist/commands/shared/codex-strays.d.ts +9 -0
  39. package/dist/commands/shared/codex-strays.d.ts.map +1 -1
  40. package/dist/commands/shared/codex-strays.js +4 -0
  41. package/dist/commands/status/index.d.ts +7 -1
  42. package/dist/commands/status/index.d.ts.map +1 -1
  43. package/dist/commands/status/index.js +53 -17
  44. package/dist/commands/sync/apply.d.ts.map +1 -1
  45. package/dist/commands/sync/apply.js +50 -24
  46. package/dist/commands/sync/dry-run.d.ts.map +1 -1
  47. package/dist/commands/sync/dry-run.js +31 -18
  48. package/dist/commands/sync/index.d.ts.map +1 -1
  49. package/dist/commands/sync/index.js +34 -25
  50. package/dist/commands/sync/sync.types.d.ts +26 -11
  51. package/dist/commands/sync/sync.types.d.ts.map +1 -1
  52. package/dist/commands/sync/sync.utils.d.ts.map +1 -1
  53. package/dist/commands/sync/sync.utils.js +3 -2
  54. package/dist/engine/index.d.ts +1 -1
  55. package/dist/engine/index.d.ts.map +1 -1
  56. package/dist/engine/index.js +1 -1
  57. package/dist/engine/scanner.d.ts +3 -1
  58. package/dist/engine/scanner.d.ts.map +1 -1
  59. package/dist/engine/scanner.js +4 -2
  60. package/dist/providers/ceiling/registry.d.ts +2 -0
  61. package/dist/providers/ceiling/registry.d.ts.map +1 -1
  62. package/dist/providers/ceiling/registry.js +20 -4
  63. package/dist/providers/codex/codec/sync-extension.d.ts +11 -10
  64. package/dist/providers/codex/codec/sync-extension.d.ts.map +1 -1
  65. package/dist/providers/codex/codec/sync-extension.js +42 -14
  66. package/dist/providers/cursor/codec/catalog.d.ts +18 -0
  67. package/dist/providers/cursor/codec/catalog.d.ts.map +1 -0
  68. package/dist/providers/cursor/codec/catalog.js +39 -0
  69. package/dist/providers/cursor/codec/materialize.d.ts +24 -0
  70. package/dist/providers/cursor/codec/materialize.d.ts.map +1 -0
  71. package/dist/providers/cursor/codec/materialize.js +166 -0
  72. package/dist/providers/cursor/codec/shared.d.ts +14 -0
  73. package/dist/providers/cursor/codec/shared.d.ts.map +1 -0
  74. package/dist/providers/cursor/codec/shared.js +76 -0
  75. package/dist/providers/cursor/codec/sync-extension.d.ts +37 -0
  76. package/dist/providers/cursor/codec/sync-extension.d.ts.map +1 -0
  77. package/dist/providers/cursor/codec/sync-extension.js +393 -0
  78. package/dist/providers/cursor/index.d.ts +3 -0
  79. package/dist/providers/cursor/index.d.ts.map +1 -1
  80. package/dist/providers/cursor/index.js +3 -0
  81. package/dist/providers/identity/availability.d.ts +7 -0
  82. package/dist/providers/identity/availability.d.ts.map +1 -1
  83. package/dist/providers/identity/availability.js +23 -0
  84. package/dist/providers/shared/index.d.ts +2 -0
  85. package/dist/providers/shared/index.d.ts.map +1 -1
  86. package/dist/providers/shared/index.js +1 -0
  87. package/dist/providers/shared/materialization-extension.d.ts +44 -0
  88. package/dist/providers/shared/materialization-extension.d.ts.map +1 -0
  89. package/dist/providers/shared/materialization-extension.js +26 -0
  90. package/package.json +2 -2
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/commands/project/dispatch-ceiling/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAEL,KAAK,cAAc,EACnB,KAAK,aAAa,EACnB,MAAM,sBAAsB,CAAC;AAa9B,OAAO,EAUL,KAAK,uBAAuB,EAY7B,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAEL,KAAK,cAAc,EAEpB,MAAM,iBAAiB,CAAC;AAsBzB,OAAO,EAAE,OAAO,EAAU,MAAM,WAAW,CAAC;AAiC5C,UAAU,2BAA2B;IACnC,mBAAmB,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,cAAc,CAAC;IAChE,kBAAkB,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACrD,sBAAsB,EAAE,CACtB,QAAQ,EAAE,MAAM,EAChB,aAAa,EAAE,MAAM,EACrB,GAAG,EAAE,MAAM,CAAC,UAAU,KACnB,OAAO,CAAC,cAAc,CAAC,CAAC;IAC7B,oBAAoB,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,uBAAuB,CAAC,CAAC;IAC7E,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IAC5C,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAC/C,UAAU,EAAE,MAAM,CAAC,UAAU,CAAC;CAC/B;AAqmFD,wBAAgB,mCAAmC,CACjD,SAAS,GAAE,OAAO,CAAC,2BAA2B,CAAM,GACnD,OAAO,CAkGT"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/commands/project/dispatch-ceiling/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAEL,KAAK,cAAc,EACnB,KAAK,aAAa,EACnB,MAAM,sBAAsB,CAAC;AAa9B,OAAO,EAUL,KAAK,uBAAuB,EAY7B,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAEL,KAAK,cAAc,EAEpB,MAAM,iBAAiB,CAAC;AAsBzB,OAAO,EAAE,OAAO,EAAU,MAAM,WAAW,CAAC;AAiC5C,UAAU,2BAA2B;IACnC,mBAAmB,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,cAAc,CAAC;IAChE,kBAAkB,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACrD,sBAAsB,EAAE,CACtB,QAAQ,EAAE,MAAM,EAChB,aAAa,EAAE,MAAM,EACrB,GAAG,EAAE,MAAM,CAAC,UAAU,KACnB,OAAO,CAAC,cAAc,CAAC,CAAC;IAC7B,oBAAoB,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,uBAAuB,CAAC,CAAC;IAC7E,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IAC5C,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAC/C,UAAU,EAAE,MAAM,CAAC,UAAU,CAAC;CAC/B;AAmnFD,wBAAgB,mCAAmC,CACjD,SAAS,GAAE,OAAO,CAAC,2BAA2B,CAAM,GACnD,OAAO,CAkGT"}
@@ -210,10 +210,10 @@ function uncappedPreferredTier(provider, role, preferredValue) {
210
210
  }
211
211
  function dispatchValueFromRouteTarget(target) {
212
212
  const adapter = getCeilingAdapter(target.harness);
213
- if (adapter.mechanism === 'pinned-variant') {
213
+ if (adapter.selectionAxis === 'model-effort') {
214
214
  return target.effort ?? null;
215
215
  }
216
- if (adapter.mechanism === 'model-arg') {
216
+ if (adapter.selectionAxis === 'model' || adapter.selectionAxis === 'tier') {
217
217
  return target.model ?? null;
218
218
  }
219
219
  return null;
@@ -226,7 +226,7 @@ function routeTargetFromBareValue(provider, value, routeIndex, routeLength) {
226
226
  routeIndex,
227
227
  routeLength,
228
228
  };
229
- if (adapter.mechanism === 'pinned-variant') {
229
+ if (adapter.selectionAxis === 'model-effort') {
230
230
  target.effort = value;
231
231
  }
232
232
  else {
@@ -398,13 +398,15 @@ function candidatePrimaryTarget(provider, tier, candidate) {
398
398
  throw new Error(`Malformed ${provider} candidate ordering in ${tier}: direct dispatch role names are not candidate models.`);
399
399
  }
400
400
  const targetAdapter = getCeilingAdapter(target.harness);
401
- if (targetAdapter.mechanism === 'pinned-variant' &&
401
+ if (targetAdapter.selectionAxis === 'model-effort' &&
402
402
  (!target.model ||
403
403
  !target.effort ||
404
404
  !CODEX_VALUES.includes(target.effort))) {
405
405
  throw new Error(`Malformed ${provider} candidate ordering in ${tier}: Codex candidates require a model and supported effort.`);
406
406
  }
407
- if (targetAdapter.mechanism === 'model-arg' && !target.model) {
407
+ if ((targetAdapter.selectionAxis === 'model' ||
408
+ targetAdapter.selectionAxis === 'tier') &&
409
+ !target.model) {
408
410
  throw new Error(`Malformed ${provider} candidate ordering in ${tier}: model-argument candidates require a model.`);
409
411
  }
410
412
  return target;
@@ -1053,7 +1055,7 @@ function selectDispatchValue(provider, role, policy, preferredValue) {
1053
1055
  target: selectedTarget,
1054
1056
  };
1055
1057
  }
1056
- function hasCodexVariantDispatchArgs(dispatchArgs) {
1058
+ function hasVariantDispatchArgs(dispatchArgs) {
1057
1059
  return (dispatchArgs !== null &&
1058
1060
  'variant' in dispatchArgs &&
1059
1061
  typeof dispatchArgs.variant === 'string' &&
@@ -1065,20 +1067,26 @@ function hasModelDispatchArgs(dispatchArgs) {
1065
1067
  typeof dispatchArgs.model === 'string' &&
1066
1068
  dispatchArgs.model.length > 0);
1067
1069
  }
1068
- function modelAxis(selection, dispatchArgs) {
1070
+ function modelAxis(provider, selection, dispatchArgs) {
1069
1071
  if (selection.target?.model && dispatchArgs) {
1070
1072
  return `selected:${selection.target.model}`;
1071
1073
  }
1072
1074
  if (hasModelDispatchArgs(dispatchArgs)) {
1073
1075
  return `selected:${dispatchArgs.model}`;
1074
1076
  }
1077
+ if (provider === 'cursor' &&
1078
+ hasVariantDispatchArgs(dispatchArgs) &&
1079
+ selection.target === null &&
1080
+ selection.selectedValue) {
1081
+ return `selected:${selection.selectedValue}`;
1082
+ }
1075
1083
  if (selection.selectionMode === 'inherit-default') {
1076
1084
  return 'inherited';
1077
1085
  }
1078
1086
  return 'unresolved';
1079
1087
  }
1080
1088
  function codexEffortAxis(selection, dispatchArgs) {
1081
- if (hasCodexVariantDispatchArgs(dispatchArgs) && selection.target?.effort) {
1089
+ if (hasVariantDispatchArgs(dispatchArgs) && selection.target?.effort) {
1082
1090
  return `selected:${selection.target.effort}`;
1083
1091
  }
1084
1092
  if (selection.selectionMode === 'inherit-default' ||
@@ -1149,7 +1157,7 @@ function buildProviderResolution(provider, policy, role, orchestratorTier, prefe
1149
1157
  mode,
1150
1158
  mechanism: adapter.mechanism,
1151
1159
  dispatchArgs,
1152
- modelAxis: modelAxis(selection, dispatchArgs),
1160
+ modelAxis: modelAxis(provider, selection, dispatchArgs),
1153
1161
  effortAxis: provider === 'codex'
1154
1162
  ? codexEffortAxis(selection, dispatchArgs)
1155
1163
  : 'not-applicable',
@@ -1,5 +1,6 @@
1
1
  import type { CanonicalEntry } from '../../engine/index.js';
2
2
  import type { CodexExtensionPlan } from '../../providers/codex/codec/sync-extension.js';
3
+ import type { MaterializationPlan } from '../../providers/shared/index.js';
3
4
  export interface CodexRoleStray {
4
5
  roleName: string;
5
6
  providerPath: string;
@@ -11,6 +12,14 @@ export interface CodexRegenerationDependencies {
11
12
  computeExtensionPlan: (scopeRoot: string, canonicalEntries: CanonicalEntry[]) => Promise<CodexExtensionPlan>;
12
13
  applyExtensionPlan: (scopeRoot: string, plan: CodexExtensionPlan) => Promise<unknown>;
13
14
  }
15
+ interface ProviderStrayCandidate {
16
+ provider: string;
17
+ report: {
18
+ providerPath: string;
19
+ };
20
+ }
21
+ export declare function filterMaterializationManagedStrays<TCandidate extends ProviderStrayCandidate>(candidates: TCandidate[], plans: readonly MaterializationPlan[]): TCandidate[];
14
22
  export declare function detectCodexRoleStrays(scopeRoot: string, canonicalEntries: CanonicalEntry[], managedRoleNames?: Set<string>): Promise<CodexRoleStray[]>;
15
23
  export declare function regenerateCodexAfterAdoption({ scopeRoot, scanCanonical, computeExtensionPlan, applyExtensionPlan, }: CodexRegenerationDependencies): Promise<void>;
24
+ export {};
16
25
  //# sourceMappingURL=codex-strays.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"codex-strays.d.ts","sourceRoot":"","sources":["../../../src/commands/shared/codex-strays.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAGpD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,uCAAuC,CAAC;AAEhF,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,6BAA6B;IAC5C,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,OAAO,CAAC,cAAc,EAAE,CAAC,CAAC;IAC/C,oBAAoB,EAAE,CACpB,SAAS,EAAE,MAAM,EACjB,gBAAgB,EAAE,cAAc,EAAE,KAC/B,OAAO,CAAC,kBAAkB,CAAC,CAAC;IACjC,kBAAkB,EAAE,CAClB,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,kBAAkB,KACrB,OAAO,CAAC,OAAO,CAAC,CAAC;CACvB;AAgJD,wBAAsB,qBAAqB,CACzC,SAAS,EAAE,MAAM,EACjB,gBAAgB,EAAE,cAAc,EAAE,EAClC,gBAAgB,GAAE,GAAG,CAAC,MAAM,CAAa,GACxC,OAAO,CAAC,cAAc,EAAE,CAAC,CAuB3B;AAED,wBAAsB,4BAA4B,CAAC,EACjD,SAAS,EACT,aAAa,EACb,oBAAoB,EACpB,kBAAkB,GACnB,EAAE,6BAA6B,GAAG,OAAO,CAAC,IAAI,CAAC,CAI/C"}
1
+ {"version":3,"file":"codex-strays.d.ts","sourceRoot":"","sources":["../../../src/commands/shared/codex-strays.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAGpD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,uCAAuC,CAAC;AAChF,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAE7D,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,6BAA6B;IAC5C,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,OAAO,CAAC,cAAc,EAAE,CAAC,CAAC;IAC/C,oBAAoB,EAAE,CACpB,SAAS,EAAE,MAAM,EACjB,gBAAgB,EAAE,cAAc,EAAE,KAC/B,OAAO,CAAC,kBAAkB,CAAC,CAAC;IACjC,kBAAkB,EAAE,CAClB,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,kBAAkB,KACrB,OAAO,CAAC,OAAO,CAAC,CAAC;CACvB;AAED,UAAU,sBAAsB;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE;QAAE,YAAY,EAAE,MAAM,CAAA;KAAE,CAAC;CAClC;AAED,wBAAgB,kCAAkC,CAChD,UAAU,SAAS,sBAAsB,EAEzC,UAAU,EAAE,UAAU,EAAE,EACxB,KAAK,EAAE,SAAS,mBAAmB,EAAE,GACpC,UAAU,EAAE,CAed;AAgJD,wBAAsB,qBAAqB,CACzC,SAAS,EAAE,MAAM,EACjB,gBAAgB,EAAE,cAAc,EAAE,EAClC,gBAAgB,GAAE,GAAG,CAAC,MAAM,CAAa,GACxC,OAAO,CAAC,cAAc,EAAE,CAAC,CAuB3B;AAED,wBAAsB,4BAA4B,CAAC,EACjD,SAAS,EACT,aAAa,EACb,oBAAoB,EACpB,kBAAkB,GACnB,EAAE,6BAA6B,GAAG,OAAO,CAAC,IAAI,CAAC,CAI/C"}
@@ -2,6 +2,10 @@ import { readdir, readFile, stat } from 'node:fs/promises';
2
2
  import { join } from 'node:path';
3
3
  import TOML from '@iarna/toml';
4
4
  import { isOatManagedCodexRoleFile } from '../../providers/codex/codec/shared.js';
5
+ export function filterMaterializationManagedStrays(candidates, plans) {
6
+ const managedPaths = new Set(plans.flatMap((plan) => plan.operations.map((operation) => `${plan.provider}|${operation.path.replaceAll('\\', '/')}`)));
7
+ return candidates.filter((candidate) => !managedPaths.has(`${candidate.provider}|${candidate.report.providerPath.replaceAll('\\', '/')}`));
8
+ }
5
9
  function canonicalRoleNames(canonicalEntries) {
6
10
  return new Set(canonicalEntries
7
11
  .filter((entry) => entry.type === 'agent' && entry.isFile)
@@ -7,6 +7,7 @@ import { type CopyTransform, type DriftReport } from '../../drift/index.js';
7
7
  import { type CanonicalEntry } from '../../engine/index.js';
8
8
  import type { Manifest } from '../../manifest/index.js';
9
9
  import { type CodexExtensionPlan } from '../../providers/codex/codec/sync-extension.js';
10
+ import { type CursorExtensionPlan } from '../../providers/cursor/codec/sync-extension.js';
10
11
  import { type PathMapping, type ProviderAdapter } from '../../providers/shared/index.js';
11
12
  import { type ConcreteScope, type Scope } from '../../shared/types.js';
12
13
  import { Command } from 'commander';
@@ -18,7 +19,7 @@ interface StatusDependencies {
18
19
  readUserConfig: (userConfigDir: string) => Promise<UserConfig>;
19
20
  saveManifest: (manifestPath: string, manifest: Manifest) => Promise<void>;
20
21
  scanCanonical: (scopeRoot: string, scope: ConcreteScope) => Promise<CanonicalEntry[]>;
21
- scanBundledManagedCodexAgents: () => Promise<CanonicalEntry[]>;
22
+ scanBundledManagedAgents: () => Promise<CanonicalEntry[]>;
22
23
  getAdapters: () => ProviderAdapter[];
23
24
  getActiveAdapters: (adapters: ProviderAdapter[], scopeRoot: string) => Promise<ProviderAdapter[]>;
24
25
  getSyncMappings: (adapter: ProviderAdapter, scope: Scope) => PathMapping[];
@@ -30,6 +31,11 @@ interface StatusDependencies {
30
31
  env?: NodeJS.ProcessEnv;
31
32
  }) => Promise<CodexExtensionPlan>;
32
33
  applyCodexProjectExtensionPlan: (scopeRoot: string, plan: CodexExtensionPlan) => Promise<unknown>;
34
+ computeCursorProjectExtensionPlan: (scopeRoot: string, canonicalEntries: CanonicalEntry[], allowedCanonicalPaths?: string[], options?: {
35
+ userConfigDir?: string;
36
+ env?: NodeJS.ProcessEnv;
37
+ }) => Promise<CursorExtensionPlan>;
38
+ applyCursorProjectExtensionPlan: (scopeRoot: string, plan: CursorExtensionPlan) => Promise<unknown>;
33
39
  selectManyWithAbort: <T extends string>(message: string, choices: MultiSelectChoice<T>[], ctx: PromptContext) => Promise<T[] | null>;
34
40
  confirmAction: (message: string, ctx: PromptContext) => Promise<boolean>;
35
41
  adoptStray: (scopeRoot: string, stray: StatusStrayCandidate, manifest: Manifest, options?: {
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/status/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/status/index.ts"],"names":[],"mappings":"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"}
@@ -1,14 +1,14 @@
1
1
  import { basename, join, relative } from 'node:path';
2
2
  import { buildCommandContext, } from '../../app/command-context.js';
3
3
  import { adoptStrayToCanonical, isAdoptionConflictError, } from '../shared/adopt-stray.js';
4
- import { detectCodexRoleStrays, regenerateCodexAfterAdoption, } from '../shared/codex-strays.js';
4
+ import { detectCodexRoleStrays, filterMaterializationManagedStrays, regenerateCodexAfterAdoption, } from '../shared/codex-strays.js';
5
5
  import { withScopeOption } from '../shared/scope-option.js';
6
6
  import { confirmAction, selectManyWithAbort, } from '../shared/shared.prompts.js';
7
7
  import { readGlobalOptions, resolveConcreteScopes, } from '../shared/shared.utils.js';
8
8
  import { DEFAULT_SYNC_CONFIG, loadSyncConfig, } from '../../config/index.js';
9
9
  import { readUserConfig } from '../../config/oat-config.js';
10
10
  import { detectDrift, detectStrays, filterKnownStrays, } from '../../drift/index.js';
11
- import { HOOK_DRIFT_WARNING, HOOK_STRAY_INFO, scanBundledManagedCodexAgents, scanCanonical, } from '../../engine/index.js';
11
+ import { HOOK_DRIFT_WARNING, HOOK_STRAY_INFO, scanBundledManagedAgents, scanCanonical, } from '../../engine/index.js';
12
12
  import { normalizeToPosixPath, resolveProjectRoot, resolveScopeRoot, } from '../../fs/paths.js';
13
13
  import { loadManifest, saveManifest } from '../../manifest/manager.js';
14
14
  import { claudeAdapter } from '../../providers/claude/index.js';
@@ -16,6 +16,7 @@ import { codexAdapter } from '../../providers/codex/index.js';
16
16
  import { applyCodexProjectExtensionPlan, computeCodexProjectExtensionPlan, } from '../../providers/codex/codec/sync-extension.js';
17
17
  import { copilotAdapter } from '../../providers/copilot/index.js';
18
18
  import { cursorAdapter } from '../../providers/cursor/index.js';
19
+ import { applyCursorProjectExtensionPlan, computeCursorProjectExtensionPlan, } from '../../providers/cursor/codec/sync-extension.js';
19
20
  import { geminiAdapter } from '../../providers/gemini/index.js';
20
21
  import { getActiveAdapters, getSyncMappings, } from '../../providers/shared/index.js';
21
22
  import { SCOPE_CONTENT_TYPES, } from '../../shared/types.js';
@@ -37,7 +38,7 @@ const DEFAULT_DEPENDENCIES = {
37
38
  readUserConfig,
38
39
  saveManifest,
39
40
  scanCanonical,
40
- scanBundledManagedCodexAgents,
41
+ scanBundledManagedAgents,
41
42
  getAdapters() {
42
43
  return [
43
44
  claudeAdapter,
@@ -54,6 +55,8 @@ const DEFAULT_DEPENDENCIES = {
54
55
  detectCodexRoleStrays,
55
56
  computeCodexProjectExtensionPlan,
56
57
  applyCodexProjectExtensionPlan,
58
+ computeCursorProjectExtensionPlan,
59
+ applyCursorProjectExtensionPlan,
57
60
  selectManyWithAbort,
58
61
  confirmAction,
59
62
  adoptStray: adoptStrayDefault,
@@ -133,6 +136,38 @@ async function collectScopeReports(scope, context, dependencies) {
133
136
  const reports = [];
134
137
  const strayCandidates = [];
135
138
  const trackedCanonicalByProvider = new Set(manifest.entries.map((entry) => `${entry.provider}|${normalizeToPosixPath(entry.canonicalPath)}`));
139
+ const activeProviderNames = new Set(activeAdapters.map((adapter) => adapter.name));
140
+ const extensionCanonicalEntries = scope === 'user' &&
141
+ (activeProviderNames.has('codex') || activeProviderNames.has('cursor'))
142
+ ? [
143
+ ...canonicalEntries,
144
+ ...(await dependencies.scanBundledManagedAgents()),
145
+ ]
146
+ : canonicalEntries;
147
+ const codexExtensionPlan = activeProviderNames.has('codex')
148
+ ? await dependencies.computeCodexProjectExtensionPlan(scopeRoot, extensionCanonicalEntries, undefined, { userConfigDir })
149
+ : undefined;
150
+ const cursorExtensionPlan = activeProviderNames.has('cursor')
151
+ ? await dependencies.computeCursorProjectExtensionPlan(scopeRoot, extensionCanonicalEntries, undefined, { userConfigDir })
152
+ : undefined;
153
+ const materializationPlans = [
154
+ ...(codexExtensionPlan
155
+ ? [
156
+ {
157
+ provider: 'codex',
158
+ operations: codexExtensionPlan.operations.map((operation) => ({
159
+ ...operation,
160
+ provider: 'codex',
161
+ entryName: operation.roleName,
162
+ })),
163
+ managedEntries: codexExtensionPlan.managedRoles,
164
+ aggregateHash: codexExtensionPlan.aggregateConfigHash,
165
+ metadata: codexExtensionPlan.metadata,
166
+ },
167
+ ]
168
+ : []),
169
+ ...(cursorExtensionPlan ? [cursorExtensionPlan] : []),
170
+ ];
136
171
  for (const adapter of activeAdapters) {
137
172
  const mappings = dependencies.getSyncMappings(adapter, scope);
138
173
  const mappingContentTypes = new Set(mappings.map((mapping) => mapping.contentType));
@@ -179,7 +214,7 @@ async function collectScopeReports(scope, context, dependencies) {
179
214
  }
180
215
  for (const mapping of mappings) {
181
216
  const providerDir = join(scopeRoot, mapping.providerDir);
182
- const strays = await dependencies.detectStrays(adapter.name, providerDir, manifest, canonicalEntries, mapping);
217
+ const strays = filterMaterializationManagedStrays((await dependencies.detectStrays(adapter.name, providerDir, manifest, canonicalEntries, mapping)).map((report) => ({ provider: adapter.name, report })), materializationPlans).map((candidate) => candidate.report);
183
218
  reports.push(...strays);
184
219
  for (const stray of strays) {
185
220
  if (stray.state.status !== 'stray') {
@@ -193,24 +228,17 @@ async function collectScopeReports(scope, context, dependencies) {
193
228
  }
194
229
  }
195
230
  }
196
- if (activeAdapters.some((adapter) => adapter.name === 'codex')) {
197
- const codexCanonicalEntries = scope === 'user'
198
- ? [
199
- ...canonicalEntries,
200
- ...(await dependencies.scanBundledManagedCodexAgents()),
201
- ]
202
- : canonicalEntries;
203
- const codexExtensionPlan = await dependencies.computeCodexProjectExtensionPlan(scopeRoot, codexCanonicalEntries, undefined, { userConfigDir: join(context.home, '.oat') });
204
- for (const operation of codexExtensionPlan.operations) {
231
+ for (const extensionPlan of materializationPlans) {
232
+ for (const operation of extensionPlan.operations) {
205
233
  if (operation.action === 'skip') {
206
234
  continue;
207
235
  }
208
236
  if (operation.target === 'role') {
209
237
  reports.push({
210
- canonical: operation.roleName
211
- ? `.agents/agents/${operation.roleName}.md`
238
+ canonical: operation.entryName
239
+ ? `.agents/agents/${operation.entryName}.md`
212
240
  : null,
213
- provider: 'codex',
241
+ provider: extensionPlan.provider,
214
242
  providerPath: operation.path,
215
243
  state: operation.action === 'create'
216
244
  ? { status: 'missing' }
@@ -220,12 +248,14 @@ async function collectScopeReports(scope, context, dependencies) {
220
248
  else {
221
249
  reports.push({
222
250
  canonical: null,
223
- provider: 'codex',
251
+ provider: extensionPlan.provider,
224
252
  providerPath: operation.path,
225
253
  state: { status: 'drifted', reason: 'modified' },
226
254
  });
227
255
  }
228
256
  }
257
+ }
258
+ if (codexExtensionPlan) {
229
259
  const codexStrays = await dependencies.detectCodexRoleStrays(scopeRoot, canonicalEntries, new Set(codexExtensionPlan.managedRoles));
230
260
  for (const codexStray of codexStrays) {
231
261
  const report = {
@@ -267,6 +297,7 @@ async function collectScopeReports(scope, context, dependencies) {
267
297
  manifest,
268
298
  reports: filtered.reports,
269
299
  strayCandidates: filtered.candidates,
300
+ activeAdapterNames: activeAdapters.map((adapter) => adapter.name),
270
301
  };
271
302
  }
272
303
  async function runStatusCommand(context, dependencies, options = {}) {
@@ -356,6 +387,11 @@ async function runStatusCommand(context, dependencies, options = {}) {
356
387
  computeExtensionPlan: dependencies.computeCodexProjectExtensionPlan,
357
388
  applyExtensionPlan: dependencies.applyCodexProjectExtensionPlan,
358
389
  });
390
+ if (scopeCollection.activeAdapterNames.includes('cursor')) {
391
+ const canonicalEntries = await dependencies.scanCanonical(scopeCollection.scopeRoot, scopeCollection.scope);
392
+ const cursorPlan = await dependencies.computeCursorProjectExtensionPlan(scopeCollection.scopeRoot, canonicalEntries, undefined, { userConfigDir: join(context.home, '.oat') });
393
+ await dependencies.applyCursorProjectExtensionPlan(scopeCollection.scopeRoot, cursorPlan);
394
+ }
359
395
  }
360
396
  if (manifestChanged) {
361
397
  await dependencies.saveManifest(scopeCollection.manifestPath, scopeCollection.manifest);
@@ -1 +1 @@
1
- {"version":3,"file":"apply.d.ts","sourceRoot":"","sources":["../../../src/commands/sync/apply.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAG3D,OAAO,KAAK,EACV,aAAa,EACb,uBAAuB,EAExB,MAAM,cAAc,CAAC;AAgEtB,wBAAsB,YAAY,CAChC,OAAO,EAAE,cAAc,EACvB,UAAU,EAAE,aAAa,EAAE,EAC3B,YAAY,EAAE,uBAAuB,GACpC,OAAO,CAAC,IAAI,CAAC,CA8Ef"}
1
+ {"version":3,"file":"apply.d.ts","sourceRoot":"","sources":["../../../src/commands/sync/apply.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAG3D,OAAO,KAAK,EACV,aAAa,EACb,uBAAuB,EAExB,MAAM,cAAc,CAAC;AAyEtB,wBAAsB,YAAY,CAChC,OAAO,EAAE,cAAc,EACvB,UAAU,EAAE,aAAa,EAAE,EAC3B,YAAY,EAAE,uBAAuB,GACpC,OAAO,CAAC,IAAI,CAAC,CAyGf"}
@@ -2,11 +2,13 @@ import { OAT_VERSION } from '../../shared/oat-version.js';
2
2
  import { countPlannedOperations } from './sync.utils.js';
3
3
  function countSkippedEntries(scopePlans) {
4
4
  return scopePlans.reduce((total, scopePlan) => {
5
- const codexSkipped = scopePlan.codexExtension?.operations.filter((operation) => operation.action === 'skip').length ?? 0;
5
+ const extensionSkipped = scopePlan.materializationExtensions.reduce((count, extension) => count +
6
+ extension.operations.filter((operation) => operation.action === 'skip')
7
+ .length, 0);
6
8
  return (total +
7
9
  scopePlan.plan.entries.filter((entry) => entry.operation === 'skip')
8
10
  .length +
9
- codexSkipped);
11
+ extensionSkipped);
10
12
  }, 0);
11
13
  }
12
14
  function buildSummary(scopePlans, applied, failed) {
@@ -28,15 +30,19 @@ function formatAppliedOutput(scopePlans, dependencies) {
28
30
  return scopePlans
29
31
  .map((scopePlan) => {
30
32
  const syncOutput = dependencies.formatSyncPlan(scopePlan.plan, true);
31
- const codexExtension = scopePlan.codexExtension;
32
- if (!codexExtension) {
33
+ if (scopePlan.materializationExtensions.length === 0) {
33
34
  return `Scope: ${scopePlan.scope}\n${syncOutput}`;
34
35
  }
35
- const codexLines = codexExtension.operations.map((operation) => {
36
- const role = operation.roleName ? ` (${operation.roleName})` : '';
37
- return `- codex:${operation.target}:${operation.action} ${operation.path}${role} (${operation.reason})`;
36
+ const extensionSections = scopePlan.materializationExtensions.map((extension) => {
37
+ const lines = extension.operations.map((operation) => {
38
+ const entry = operation.entryName
39
+ ? ` (${operation.entryName})`
40
+ : '';
41
+ return `- ${operation.provider}:${operation.target}:${operation.action} ${operation.path}${entry} (${operation.reason})`;
42
+ });
43
+ return `${extension.provider} extension (applied)\n${lines.join('\n')}`;
38
44
  });
39
- return `Scope: ${scopePlan.scope}\n${syncOutput}\n\nCodex extension (applied)\n${codexLines.join('\n')}`;
45
+ return `Scope: ${scopePlan.scope}\n${syncOutput}\n\n${extensionSections.join('\n\n')}`;
40
46
  })
41
47
  .join('\n\n');
42
48
  }
@@ -45,10 +51,10 @@ export async function runSyncApply(context, scopePlans, dependencies) {
45
51
  let failed = 0;
46
52
  for (const scopePlan of scopePlans) {
47
53
  const hasSyncEntries = scopePlan.plan.entries.length > 0 || scopePlan.plan.removals.length > 0;
48
- const hasCodexPlannedOperations = scopePlan.codexExtensionPlan?.operations.some((operation) => operation.action !== 'skip') ?? false;
54
+ const hasExtensionPlannedOperations = scopePlan.materializationExtensionPlans.some((plan) => plan.operations.some((operation) => operation.action !== 'skip'));
49
55
  const shouldRefreshManifestVersion = scopePlan.manifest.oatVersion !== OAT_VERSION;
50
56
  if (!hasSyncEntries &&
51
- !hasCodexPlannedOperations &&
57
+ !hasExtensionPlannedOperations &&
52
58
  !shouldRefreshManifestVersion) {
53
59
  continue;
54
60
  }
@@ -57,17 +63,22 @@ export async function runSyncApply(context, scopePlans, dependencies) {
57
63
  applied += result.applied;
58
64
  failed += result.failed;
59
65
  }
60
- if (scopePlan.codexExtensionPlan && hasCodexPlannedOperations) {
61
- const codexResult = await dependencies.applyCodexProjectExtensionPlan(scopePlan.scopeRoot, scopePlan.codexExtensionPlan);
62
- applied += codexResult.applied;
63
- failed += codexResult.failed;
64
- if (scopePlan.codexExtension) {
65
- scopePlan.codexExtension = {
66
- ...scopePlan.codexExtension,
67
- applied: codexResult.applied,
68
- failed: codexResult.failed,
69
- skipped: codexResult.skipped,
70
- };
66
+ for (const plan of scopePlan.materializationExtensionPlans) {
67
+ if (!plan.operations.some((operation) => operation.action !== 'skip')) {
68
+ continue;
69
+ }
70
+ const extension = dependencies
71
+ .getMaterializationExtensions()
72
+ .find((candidate) => candidate.provider === plan.provider);
73
+ if (!extension) {
74
+ throw new Error(`Materialization extension ${plan.provider} disappeared before apply.`);
75
+ }
76
+ const result = await dependencies.applyMaterializationExtensionPlan(extension, scopePlan.scopeRoot, plan);
77
+ applied += result.applied;
78
+ failed += result.failed;
79
+ const summary = scopePlan.materializationExtensions.find((candidate) => candidate.provider === plan.provider);
80
+ if (summary) {
81
+ Object.assign(summary, result);
71
82
  }
72
83
  }
73
84
  }
@@ -75,9 +86,23 @@ export async function runSyncApply(context, scopePlans, dependencies) {
75
86
  const providerMismatches = scopePlans
76
87
  .map((scopePlan) => scopePlan.providerMismatches)
77
88
  .filter((mismatch) => mismatch !== undefined);
78
- const codexExtensions = scopePlans
79
- .map((scopePlan) => scopePlan.codexExtension)
80
- .filter((extension) => extension !== undefined);
89
+ const materializationExtensions = scopePlans.flatMap((scopePlan) => scopePlan.materializationExtensions);
90
+ const codexExtensions = materializationExtensions
91
+ .filter((extension) => extension.provider === 'codex')
92
+ .map((extension) => ({
93
+ operations: extension.operations.map((operation) => ({
94
+ action: operation.action,
95
+ target: operation.target,
96
+ path: operation.path,
97
+ reason: operation.reason,
98
+ roleName: operation.entryName,
99
+ })),
100
+ managedRoles: extension.managedEntries,
101
+ aggregateConfigHash: extension.aggregateHash,
102
+ applied: extension.applied,
103
+ failed: extension.failed,
104
+ skipped: extension.skipped,
105
+ }));
81
106
  if (context.json) {
82
107
  context.logger.json({
83
108
  scope: context.scope,
@@ -85,6 +110,7 @@ export async function runSyncApply(context, scopePlans, dependencies) {
85
110
  plans: scopePlans.map((scopePlan) => scopePlan.plan),
86
111
  summary,
87
112
  providerMismatches,
113
+ materializationExtensions,
88
114
  codexExtensions,
89
115
  });
90
116
  }
@@ -1 +1 @@
1
- {"version":3,"file":"dry-run.d.ts","sourceRoot":"","sources":["../../../src/commands/sync/dry-run.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAE3D,OAAO,KAAK,EACV,aAAa,EACb,uBAAuB,EAExB,MAAM,cAAc,CAAC;AA+DtB,wBAAgB,aAAa,CAC3B,OAAO,EAAE,cAAc,EACvB,UAAU,EAAE,aAAa,EAAE,EAC3B,YAAY,EAAE,uBAAuB,GACpC,IAAI,CA6BN"}
1
+ {"version":3,"file":"dry-run.d.ts","sourceRoot":"","sources":["../../../src/commands/sync/dry-run.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAE3D,OAAO,KAAK,EACV,aAAa,EACb,uBAAuB,EAExB,MAAM,cAAc,CAAC;AAiEtB,wBAAgB,aAAa,CAC3B,OAAO,EAAE,cAAc,EACvB,UAAU,EAAE,aAAa,EAAE,EAC3B,YAAY,EAAE,uBAAuB,GACpC,IAAI,CA2CN"}
@@ -5,24 +5,25 @@ function summarize(scopePlans) {
5
5
  applied: 0,
6
6
  failed: 0,
7
7
  skipped: scopePlans.reduce((total, scopePlan) => {
8
- const codexSkipped = scopePlan.codexExtension?.operations.filter((operation) => operation.action === 'skip').length ?? 0;
8
+ const extensionSkipped = scopePlan.materializationExtensions.reduce((count, extension) => count +
9
+ extension.operations.filter((operation) => operation.action === 'skip').length, 0);
9
10
  return (total +
10
11
  scopePlan.plan.entries.filter((entry) => entry.operation === 'skip')
11
12
  .length +
12
- codexSkipped);
13
+ extensionSkipped);
13
14
  }, 0),
14
15
  };
15
16
  }
16
- function formatCodexExtension(scopePlan) {
17
- const codexExtension = scopePlan.codexExtension;
18
- if (!codexExtension) {
19
- return '';
20
- }
21
- const lines = codexExtension.operations.map((operation) => {
22
- const role = operation.roleName ? ` (${operation.roleName})` : '';
23
- return `- codex:${operation.target}:${operation.action} ${operation.path}${role} (${operation.reason})`;
24
- });
25
- return `Codex extension (dry-run)\n${lines.join('\n')}`;
17
+ function formatMaterializationExtensions(scopePlan) {
18
+ return scopePlan.materializationExtensions
19
+ .map((extension) => {
20
+ const lines = extension.operations.map((operation) => {
21
+ const entry = operation.entryName ? ` (${operation.entryName})` : '';
22
+ return `- ${operation.provider}:${operation.target}:${operation.action} ${operation.path}${entry} (${operation.reason})`;
23
+ });
24
+ return `${extension.provider} extension (dry-run)\n${lines.join('\n')}`;
25
+ })
26
+ .join('\n\n');
26
27
  }
27
28
  function formatDryRunOutput(scopePlans, dependencies) {
28
29
  if (scopePlans.length === 0) {
@@ -35,9 +36,9 @@ function formatDryRunOutput(scopePlans, dependencies) {
35
36
  return scopePlans
36
37
  .map((scopePlan) => {
37
38
  const syncOutput = dependencies.formatSyncPlan(scopePlan.plan, false);
38
- const codexOutput = formatCodexExtension(scopePlan);
39
- return codexOutput
40
- ? `Scope: ${scopePlan.scope}\n${syncOutput}\n\n${codexOutput}`
39
+ const extensionOutput = formatMaterializationExtensions(scopePlan);
40
+ return extensionOutput
41
+ ? `Scope: ${scopePlan.scope}\n${syncOutput}\n\n${extensionOutput}`
41
42
  : `Scope: ${scopePlan.scope}\n${syncOutput}`;
42
43
  })
43
44
  .join('\n\n');
@@ -47,9 +48,20 @@ export function runSyncDryRun(context, scopePlans, dependencies) {
47
48
  const providerMismatches = scopePlans
48
49
  .map((scopePlan) => scopePlan.providerMismatches)
49
50
  .filter((mismatch) => mismatch !== undefined);
50
- const codexExtensions = scopePlans
51
- .map((scopePlan) => scopePlan.codexExtension)
52
- .filter((extension) => extension !== undefined);
51
+ const materializationExtensions = scopePlans.flatMap((scopePlan) => scopePlan.materializationExtensions);
52
+ const codexExtensions = materializationExtensions
53
+ .filter((extension) => extension.provider === 'codex')
54
+ .map((extension) => ({
55
+ operations: extension.operations.map((operation) => ({
56
+ action: operation.action,
57
+ target: operation.target,
58
+ path: operation.path,
59
+ reason: operation.reason,
60
+ roleName: operation.entryName,
61
+ })),
62
+ managedRoles: extension.managedEntries,
63
+ aggregateConfigHash: extension.aggregateHash,
64
+ }));
53
65
  if (context.json) {
54
66
  context.logger.json({
55
67
  scope: context.scope,
@@ -57,6 +69,7 @@ export function runSyncDryRun(context, scopePlans, dependencies) {
57
69
  plans: scopePlans.map((scopePlan) => scopePlan.plan),
58
70
  summary,
59
71
  providerMismatches,
72
+ materializationExtensions,
60
73
  codexExtensions,
61
74
  });
62
75
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/sync/index.ts"],"names":[],"mappings":"AA4CA,OAAO,EAAE,OAAO,EAAU,MAAM,WAAW,CAAC;AAI5C,OAAO,KAAK,EAEV,uBAAuB,EAExB,MAAM,cAAc,CAAC;AA6TtB,wBAAgB,iBAAiB,CAC/B,SAAS,GAAE,OAAO,CAAC,uBAAuB,CAAM,GAC/C,OAAO,CA6BT"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/sync/index.ts"],"names":[],"mappings":"AA0CA,OAAO,EAAE,OAAO,EAAU,MAAM,WAAW,CAAC;AAI5C,OAAO,KAAK,EAEV,uBAAuB,EAExB,MAAM,cAAc,CAAC;AAwUtB,wBAAgB,iBAAiB,CAC/B,SAAS,GAAE,OAAO,CAAC,uBAAuB,CAAM,GAC/C,OAAO,CA6BT"}