@straion/cli 0.0.1 → 0.0.3

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 (174) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/README.md +0 -4
  3. package/dist/cli.d.ts.map +1 -1
  4. package/dist/cli.js +2 -4
  5. package/dist/cli.js.map +1 -1
  6. package/dist/commands/default.d.ts.map +1 -1
  7. package/dist/commands/default.js +7 -30
  8. package/dist/commands/default.js.map +1 -1
  9. package/dist/commands/find-requirements.d.ts.map +1 -1
  10. package/dist/commands/find-requirements.integration.test.d.ts +5 -0
  11. package/dist/commands/find-requirements.integration.test.d.ts.map +1 -0
  12. package/dist/commands/find-requirements.integration.test.js +92 -0
  13. package/dist/commands/find-requirements.integration.test.js.map +1 -0
  14. package/dist/commands/find-requirements.js +26 -7
  15. package/dist/commands/find-requirements.js.map +1 -1
  16. package/dist/commands/index.d.ts.map +1 -1
  17. package/dist/commands/index.js +2 -0
  18. package/dist/commands/index.js.map +1 -1
  19. package/dist/commands/login.d.ts.map +1 -1
  20. package/dist/commands/login.integration.test.d.ts +13 -0
  21. package/dist/commands/login.integration.test.d.ts.map +1 -0
  22. package/dist/commands/login.integration.test.js +67 -0
  23. package/dist/commands/login.integration.test.js.map +1 -0
  24. package/dist/commands/login.js +20 -5
  25. package/dist/commands/login.js.map +1 -1
  26. package/dist/commands/logout.d.ts.map +1 -1
  27. package/dist/commands/logout.js +9 -14
  28. package/dist/commands/logout.js.map +1 -1
  29. package/dist/commands/session-start.d.ts.map +1 -1
  30. package/dist/commands/session-start.js +1 -2
  31. package/dist/commands/session-start.js.map +1 -1
  32. package/dist/commands/setup.d.ts +3 -0
  33. package/dist/commands/setup.d.ts.map +1 -0
  34. package/dist/commands/setup.js +23 -0
  35. package/dist/commands/setup.js.map +1 -0
  36. package/dist/components/banner.d.ts +3 -0
  37. package/dist/components/banner.d.ts.map +1 -0
  38. package/dist/components/banner.js +13 -0
  39. package/dist/components/banner.js.map +1 -0
  40. package/dist/components/button.d.ts +2 -2
  41. package/dist/components/button.d.ts.map +1 -1
  42. package/dist/components/button.js +3 -3
  43. package/dist/components/button.js.map +1 -1
  44. package/dist/components/default-flow.d.ts +11 -0
  45. package/dist/components/default-flow.d.ts.map +1 -0
  46. package/dist/components/default-flow.js +64 -0
  47. package/dist/components/default-flow.js.map +1 -0
  48. package/dist/components/hero.d.ts +2 -1
  49. package/dist/components/hero.d.ts.map +1 -1
  50. package/dist/components/hero.js +79 -19
  51. package/dist/components/hero.js.map +1 -1
  52. package/dist/components/link.d.ts +2 -2
  53. package/dist/components/link.d.ts.map +1 -1
  54. package/dist/components/link.js +3 -3
  55. package/dist/components/link.js.map +1 -1
  56. package/dist/components/login/login-error.d.ts +6 -0
  57. package/dist/components/login/login-error.d.ts.map +1 -0
  58. package/dist/components/login/login-error.js +14 -0
  59. package/dist/components/login/login-error.js.map +1 -0
  60. package/dist/components/login/login-flow.d.ts +8 -2
  61. package/dist/components/login/login-flow.d.ts.map +1 -1
  62. package/dist/components/login/login-flow.js +95 -84
  63. package/dist/components/login/login-flow.js.map +1 -1
  64. package/dist/components/login/login-flow.test.js +69 -7
  65. package/dist/components/login/login-flow.test.js.map +1 -1
  66. package/dist/components/login/types.d.ts +2 -0
  67. package/dist/components/login/types.d.ts.map +1 -0
  68. package/dist/components/login/types.js +2 -0
  69. package/dist/components/login/types.js.map +1 -0
  70. package/dist/components/login/user-settings-link.d.ts +3 -0
  71. package/dist/components/login/user-settings-link.d.ts.map +1 -0
  72. package/dist/components/login/user-settings-link.js +8 -0
  73. package/dist/components/login/user-settings-link.js.map +1 -0
  74. package/dist/components/multi-select.d.ts +16 -0
  75. package/dist/components/multi-select.d.ts.map +1 -0
  76. package/dist/components/multi-select.js +105 -0
  77. package/dist/components/multi-select.js.map +1 -0
  78. package/dist/components/org-selector.d.ts +2 -1
  79. package/dist/components/org-selector.d.ts.map +1 -1
  80. package/dist/components/org-selector.js +9 -2
  81. package/dist/components/org-selector.js.map +1 -1
  82. package/dist/components/pat-input.d.ts +2 -1
  83. package/dist/components/pat-input.d.ts.map +1 -1
  84. package/dist/components/pat-input.js +9 -3
  85. package/dist/components/pat-input.js.map +1 -1
  86. package/dist/components/pat-input.test.js +8 -8
  87. package/dist/components/pat-input.test.js.map +1 -1
  88. package/dist/components/setup/agent-setup.d.ts +9 -0
  89. package/dist/components/setup/agent-setup.d.ts.map +1 -0
  90. package/dist/components/setup/agent-setup.js +65 -0
  91. package/dist/components/setup/agent-setup.js.map +1 -0
  92. package/dist/components/setup/agents/agent-registry.d.ts +44 -0
  93. package/dist/components/setup/agents/agent-registry.d.ts.map +1 -0
  94. package/dist/components/setup/agents/agent-registry.js +64 -0
  95. package/dist/components/setup/agents/agent-registry.js.map +1 -0
  96. package/dist/components/setup/agents/command-helpers.d.ts +5 -0
  97. package/dist/components/setup/agents/command-helpers.d.ts.map +1 -0
  98. package/dist/components/setup/agents/command-helpers.js +28 -0
  99. package/dist/components/setup/agents/command-helpers.js.map +1 -0
  100. package/dist/components/setup/checking-agents.d.ts +16 -0
  101. package/dist/components/setup/checking-agents.d.ts.map +1 -0
  102. package/dist/components/setup/checking-agents.js +30 -0
  103. package/dist/components/setup/checking-agents.js.map +1 -0
  104. package/dist/components/setup/download-skills-and-plugins.d.ts +9 -0
  105. package/dist/components/setup/download-skills-and-plugins.d.ts.map +1 -0
  106. package/dist/components/setup/download-skills-and-plugins.js +29 -0
  107. package/dist/components/setup/download-skills-and-plugins.js.map +1 -0
  108. package/dist/components/setup/perform-setup.d.ts +23 -0
  109. package/dist/components/setup/perform-setup.d.ts.map +1 -0
  110. package/dist/components/setup/perform-setup.js +45 -0
  111. package/dist/components/setup/perform-setup.js.map +1 -0
  112. package/dist/components/spinner.d.ts +6 -1
  113. package/dist/components/spinner.d.ts.map +1 -1
  114. package/dist/components/spinner.js +13 -5
  115. package/dist/components/spinner.js.map +1 -1
  116. package/dist/components/tabs.d.ts +3 -3
  117. package/dist/components/tabs.d.ts.map +1 -1
  118. package/dist/components/tabs.js +26 -21
  119. package/dist/components/tabs.js.map +1 -1
  120. package/dist/hooks/use-credentials.d.ts +13 -0
  121. package/dist/hooks/use-credentials.d.ts.map +1 -0
  122. package/dist/hooks/use-credentials.js +33 -0
  123. package/dist/hooks/use-credentials.js.map +1 -0
  124. package/dist/lib/graphql.d.ts +57 -41
  125. package/dist/lib/graphql.d.ts.map +1 -1
  126. package/dist/lib/graphql.js +7 -0
  127. package/dist/lib/graphql.js.map +1 -1
  128. package/dist/lib/ink-render.d.ts +1 -1
  129. package/dist/lib/ink-render.js +1 -1
  130. package/dist/lib/logger.d.ts +13 -8
  131. package/dist/lib/logger.d.ts.map +1 -1
  132. package/dist/lib/logger.js +6 -29
  133. package/dist/lib/logger.js.map +1 -1
  134. package/dist/lib/login.d.ts.map +1 -1
  135. package/dist/lib/middleware.d.ts +2 -1
  136. package/dist/lib/middleware.d.ts.map +1 -1
  137. package/dist/lib/middleware.js +18 -6
  138. package/dist/lib/middleware.js.map +1 -1
  139. package/dist/lib/skills-manager.d.ts +33 -0
  140. package/dist/lib/skills-manager.d.ts.map +1 -0
  141. package/dist/lib/skills-manager.js +233 -0
  142. package/dist/lib/skills-manager.js.map +1 -0
  143. package/dist/lib/skills-manager.test.d.ts +7 -0
  144. package/dist/lib/skills-manager.test.d.ts.map +1 -0
  145. package/dist/lib/skills-manager.test.js +248 -0
  146. package/dist/lib/skills-manager.test.js.map +1 -0
  147. package/dist/state/global-config.d.ts +23 -9
  148. package/dist/state/global-config.d.ts.map +1 -1
  149. package/dist/state/global-config.js +42 -36
  150. package/dist/state/global-config.js.map +1 -1
  151. package/dist/state/session-manager.js +2 -2
  152. package/dist/state/session-manager.js.map +1 -1
  153. package/dist/test/integration-helpers.d.ts +96 -0
  154. package/dist/test/integration-helpers.d.ts.map +1 -0
  155. package/dist/test/integration-helpers.js +171 -0
  156. package/dist/test/integration-helpers.js.map +1 -0
  157. package/package.json +17 -4
  158. package/dist/auth/cookie-jar.d.ts +0 -24
  159. package/dist/auth/cookie-jar.d.ts.map +0 -1
  160. package/dist/auth/cookie-jar.js +0 -45
  161. package/dist/auth/cookie-jar.js.map +0 -1
  162. package/dist/components/login/login.provider.d.ts +0 -2
  163. package/dist/components/login/login.provider.d.ts.map +0 -1
  164. package/dist/components/login/login.provider.js +0 -2
  165. package/dist/components/login/login.provider.js.map +0 -1
  166. package/dist/components/login/login.store.d.ts +0 -2
  167. package/dist/components/login/login.store.d.ts.map +0 -1
  168. package/dist/components/login/login.store.js +0 -2
  169. package/dist/components/login/login.store.js.map +0 -1
  170. package/dist/state/directory-config.d.ts +0 -21
  171. package/dist/state/directory-config.d.ts.map +0 -1
  172. package/dist/state/directory-config.js +0 -59
  173. package/dist/state/directory-config.js.map +0 -1
  174. /package/{LICENSE.txt → LICENSE} +0 -0
@@ -1,5 +1,5 @@
1
1
  import { createCredentialManager } from '../auth/credentials.js';
2
- import { resolveOrg } from '../state/directory-config.js';
2
+ import { resolveOrgForDirectory } from '../state/global-config.js';
3
3
  import { createCommandLogger } from './logger.js';
4
4
  /**
5
5
  * Wrapper for command actions that provides logging only (no auth).
@@ -44,16 +44,28 @@ export function withAuthAndLogging(action) {
44
44
  context: { cwd: process.cwd() },
45
45
  });
46
46
  try {
47
- const credentialManager = await createCredentialManager();
48
- const credentials = await credentialManager.getCredentials();
49
- const resolvedOrg = resolveOrg(process.cwd());
50
- if (!credentials || !resolvedOrg) {
47
+ const envToken = process.env.STRAION_API_KEY;
48
+ let accessToken = null;
49
+ if (envToken) {
50
+ accessToken = envToken;
51
+ logger.debug('Using token from STRAION_API_KEY environment variable');
52
+ }
53
+ else {
54
+ const credentialManager = await createCredentialManager();
55
+ const credentials = await credentialManager.getCredentials();
56
+ accessToken = credentials?.accessToken ?? null;
57
+ if (accessToken) {
58
+ logger.debug('Using token from stored credentials');
59
+ }
60
+ }
61
+ const resolvedOrg = resolveOrgForDirectory(process.cwd());
62
+ if (!accessToken || !resolvedOrg) {
51
63
  console.log('No credentials for the straion cli found. Please log in first using "straion login".');
52
64
  process.exit(1);
53
65
  }
54
66
  const ctx = {
55
67
  logger,
56
- accessToken: credentials?.accessToken,
68
+ accessToken,
57
69
  organization: resolvedOrg,
58
70
  };
59
71
  return action(options, ctx, this);
@@ -1 +1 @@
1
- {"version":3,"file":"middleware.js","sourceRoot":"","sources":["../../src/lib/middleware.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AACjE,OAAO,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAG1D,OAAO,EAAE,mBAAmB,EAAuB,MAAM,aAAa,CAAC;AASvE;;;;;;;;;GASG;AACH,MAAM,UAAU,WAAW,CACzB,MAAmF;IAEnF,OAAO,KAAK,WAA0B,OAAiB;QACrD,MAAM,MAAM,GAAG,mBAAmB,CAAC,IAAI,EAAE;YACvC,SAAS,EAAE,OAAO,CAAC,OAAO;YAC1B,OAAO,EAAE,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,EAAE;SAChC,CAAC,CAAC;QAEH,IAAI,CAAC;YACH,OAAO,MAAM,MAAM,CAAC,OAAO,EAAE,EAAE,MAAM,EAAE,EAAE,IAAI,CAAC,CAAC;QACjD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,GAAG,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC;YACrE,MAAM,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE,gBAAgB,CAAC,CAAC;YAC/C,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC,CAAC;AACJ,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,kBAAkB,CAChC,MAAgF;IAEhF,OAAO,KAAK,WAA0B,OAAiB;QACrD,MAAM,MAAM,GAAG,mBAAmB,CAAC,IAAI,EAAE;YACvC,SAAS,EAAE,OAAO,CAAC,OAAO;YAC1B,OAAO,EAAE,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,EAAE;SAChC,CAAC,CAAC;QAEH,IAAI,CAAC;YACH,MAAM,iBAAiB,GAAG,MAAM,uBAAuB,EAAE,CAAC;YAC1D,MAAM,WAAW,GAAG,MAAM,iBAAiB,CAAC,cAAc,EAAE,CAAC;YAC7D,MAAM,WAAW,GAAG,UAAU,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;YAE9C,IAAI,CAAC,WAAW,IAAI,CAAC,WAAW,EAAE,CAAC;gBACjC,OAAO,CAAC,GAAG,CACT,sFAAsF,CACvF,CAAC;gBACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAClB,CAAC;YAED,MAAM,GAAG,GAAgB;gBACvB,MAAM;gBACN,WAAW,EAAE,WAAW,EAAE,WAAW;gBACrC,YAAY,EAAE,WAAW;aAC1B,CAAC;YAEF,OAAO,MAAM,CAAC,OAAO,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;QACpC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,GAAG,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC;YACrE,MAAM,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE,gBAAgB,CAAC,CAAC;YAC/C,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"middleware.js","sourceRoot":"","sources":["../../src/lib/middleware.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AACjE,OAAO,EAAE,sBAAsB,EAAE,MAAM,2BAA2B,CAAC;AAGnE,OAAO,EAAE,mBAAmB,EAAuB,MAAM,aAAa,CAAC;AAWvE;;;;;;;;;GASG;AACH,MAAM,UAAU,WAAW,CACzB,MAAiF;IAEjF,OAAO,KAAK,WAA0B,OAAiB;QACrD,MAAM,MAAM,GAAG,mBAAmB,CAAC,IAAI,EAAE;YACvC,SAAS,EAAE,OAAO,CAAC,OAAO;YAC1B,OAAO,EAAE,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,EAAE;SAChC,CAAC,CAAC;QAEH,IAAI,CAAC;YACH,OAAO,MAAM,MAAM,CAAC,OAAO,EAAE,EAAE,MAAM,EAAE,EAAE,IAAI,CAAC,CAAC;QACjD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,GAAG,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC;YACrE,MAAM,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE,gBAAgB,CAAC,CAAC;YAC/C,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC,CAAC;AACJ,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,kBAAkB,CAChC,MAAgF;IAEhF,OAAO,KAAK,WAA0B,OAAiB;QACrD,MAAM,MAAM,GAAG,mBAAmB,CAAC,IAAI,EAAE;YACvC,SAAS,EAAE,OAAO,CAAC,OAAO;YAC1B,OAAO,EAAE,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,EAAE;SAChC,CAAC,CAAC;QAEH,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC;YAC7C,IAAI,WAAW,GAAkB,IAAI,CAAC;YAEtC,IAAI,QAAQ,EAAE,CAAC;gBACb,WAAW,GAAG,QAAQ,CAAC;gBACvB,MAAM,CAAC,KAAK,CAAC,uDAAuD,CAAC,CAAC;YACxE,CAAC;iBAAM,CAAC;gBACN,MAAM,iBAAiB,GAAG,MAAM,uBAAuB,EAAE,CAAC;gBAC1D,MAAM,WAAW,GAAG,MAAM,iBAAiB,CAAC,cAAc,EAAE,CAAC;gBAC7D,WAAW,GAAG,WAAW,EAAE,WAAW,IAAI,IAAI,CAAC;gBAC/C,IAAI,WAAW,EAAE,CAAC;oBAChB,MAAM,CAAC,KAAK,CAAC,qCAAqC,CAAC,CAAC;gBACtD,CAAC;YACH,CAAC;YAED,MAAM,WAAW,GAAG,sBAAsB,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;YAE1D,IAAI,CAAC,WAAW,IAAI,CAAC,WAAW,EAAE,CAAC;gBACjC,OAAO,CAAC,GAAG,CACT,sFAAsF,CACvF,CAAC;gBACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAClB,CAAC;YAED,MAAM,GAAG,GAAgB;gBACvB,MAAM;gBACN,WAAW;gBACX,YAAY,EAAE,WAAW;aAC1B,CAAC;YAEF,OAAO,MAAM,CAAC,OAAO,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;QACpC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,GAAG,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC;YACrE,MAAM,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE,gBAAgB,CAAC,CAAC;YAC/C,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,33 @@
1
+ import { type AgentId } from '../components/setup/agents/agent-registry.js';
2
+ export declare const SKILLS_GITHUB_URL = "https://github.com/straion-dev/straion-claude-marketplace";
3
+ export type LinkType = 'symlink' | 'copy' | 'none';
4
+ export interface LinkResult {
5
+ success: boolean;
6
+ path: string;
7
+ mode: 'symlink' | 'copy' | 'plugin';
8
+ type: 'plugin' | 'skill';
9
+ error?: string;
10
+ }
11
+ declare const centralMarketplaceDir: string;
12
+ export { centralMarketplaceDir };
13
+ /**
14
+ * Check if central marketplace is downloaded
15
+ */
16
+ export declare function isDownloaded(): boolean;
17
+ /**
18
+ * Download and extract marketplace tarball from GitHub.
19
+ * The tarball root is the marketplace root containing .claude-plugin/marketplace.json
20
+ */
21
+ export declare function download(onProgress?: (msg: string) => void): Promise<void>;
22
+ /**
23
+ * Check how skill is linked for an agent
24
+ */
25
+ export declare function getLinkType(agentSkillsDir: string): LinkType;
26
+ /**
27
+ * Link skill to agent (symlink preferred, copy as fallback)
28
+ * @returns LinkResult with success status, path, and mode
29
+ */
30
+ export declare function linkSkill(agentSkillsDir: string, skillName: string): Promise<LinkResult>;
31
+ export declare function linkPlugin(installPlugin: (marketplacePath: string) => Promise<boolean>): Promise<LinkResult>;
32
+ export declare function link(agent: AgentId): Promise<LinkResult[]>;
33
+ //# sourceMappingURL=skills-manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skills-manager.d.ts","sourceRoot":"","sources":["../../src/lib/skills-manager.ts"],"names":[],"mappings":"AAeA,OAAO,EAAU,KAAK,OAAO,EAAE,MAAM,8CAA8C,CAAC;AASpF,eAAO,MAAM,iBAAiB,8DAA8D,CAAC;AAI7F,MAAM,MAAM,QAAQ,GAAG,SAAS,GAAG,MAAM,GAAG,MAAM,CAAC;AAEnD,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,SAAS,GAAG,MAAM,GAAG,QAAQ,CAAC;IACpC,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAUD,QAAA,MAAM,qBAAqB,QAAiC,CAAC;AAG7D,OAAO,EAAE,qBAAqB,EAAE,CAAC;AAEjC;;GAEG;AACH,wBAAgB,YAAY,IAAI,OAAO,CAEtC;AAED;;;GAGG;AACH,wBAAsB,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAyDhF;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,cAAc,EAAE,MAAM,GAAG,QAAQ,CAuB5D;AAeD;;;GAGG;AACH,wBAAsB,SAAS,CAAC,cAAc,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAmE9F;AAED,wBAAsB,UAAU,CAC9B,aAAa,EAAE,CAAC,eAAe,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,GAC3D,OAAO,CAAC,UAAU,CAAC,CAqBrB;AAED,wBAAsB,IAAI,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CA2BhE"}
@@ -0,0 +1,233 @@
1
+ import { exec as execCallback } from 'node:child_process';
2
+ import { existsSync, lstatSync, mkdirSync, readdirSync, readlinkSync, rmSync, symlinkSync, } from 'node:fs';
3
+ import { cp, writeFile } from 'node:fs/promises';
4
+ import { tmpdir } from 'node:os';
5
+ import { join, resolve } from 'node:path';
6
+ import { promisify } from 'node:util';
7
+ import { agents } from '../components/setup/agents/agent-registry.js';
8
+ import { ensureGlobalDir, globalDir } from '../state/global-config.js';
9
+ import { createLogger } from './logger.js';
10
+ const exec = promisify(execCallback);
11
+ const logger = createLogger();
12
+ export const SKILLS_GITHUB_URL = 'https://github.com/straion-dev/straion-claude-marketplace';
13
+ // Placeholder URL - replace with actual GitHub tarball URL
14
+ const SKILLS_GITHUB_TAR_URL = `${SKILLS_GITHUB_URL}/archive/refs/heads/main.tar.gz`;
15
+ // Central marketplace directory - the tarball root is the marketplace root
16
+ // Structure:
17
+ // ~/.straion/marketplace/
18
+ // ├── .claude-plugin/marketplace.json
19
+ // └── straion-plugin/
20
+ // ├── .claude-plugin/plugin.json
21
+ // ├── skills/straion/
22
+ // └── hooks/
23
+ const centralMarketplaceDir = join(globalDir, 'marketplace');
24
+ const centralSkillsDir = join(centralMarketplaceDir, 'straion-plugin', 'skills');
25
+ export { centralMarketplaceDir };
26
+ /**
27
+ * Check if central marketplace is downloaded
28
+ */
29
+ export function isDownloaded() {
30
+ return existsSync(centralMarketplaceDir);
31
+ }
32
+ /**
33
+ * Download and extract marketplace tarball from GitHub.
34
+ * The tarball root is the marketplace root containing .claude-plugin/marketplace.json
35
+ */
36
+ export async function download(onProgress) {
37
+ const progress = onProgress ?? (() => undefined);
38
+ progress('Fetching marketplace from GitHub...');
39
+ // Create temp directory for download
40
+ const tempDir = join(tmpdir(), `straion-marketplace-${Date.now()}`);
41
+ mkdirSync(tempDir, { recursive: true });
42
+ try {
43
+ // Fetch the tarball
44
+ const response = await fetch(SKILLS_GITHUB_TAR_URL);
45
+ if (!response.ok) {
46
+ throw new Error(`Failed to download: ${response.status} ${response.statusText}`);
47
+ }
48
+ const arrayBuffer = await response.arrayBuffer();
49
+ const tarballPath = join(tempDir, 'marketplace.tar.gz');
50
+ await writeFile(tarballPath, Buffer.from(arrayBuffer));
51
+ progress('Extracting skills and plugins...');
52
+ const extractDir = join(tempDir, 'extracted');
53
+ mkdirSync(extractDir, { recursive: true });
54
+ await exec(`tar -xzf "${tarballPath}" -C "${extractDir}"`);
55
+ // Find the extracted directory (GitHub tarballs extract to repo-branch/)
56
+ const extractedContents = readdirSync(extractDir);
57
+ if (extractedContents.length === 0) {
58
+ throw new Error('Extracted tarball is empty');
59
+ }
60
+ const extractedDir = join(extractDir, extractedContents[0]);
61
+ // Ensure global directory exists
62
+ ensureGlobalDir();
63
+ // Remove existing marketplace if present
64
+ if (existsSync(centralMarketplaceDir)) {
65
+ rmSync(centralMarketplaceDir, { recursive: true, force: true });
66
+ }
67
+ // Copy the entire extracted repo as the marketplace
68
+ // The tarball root is the marketplace root with structure:
69
+ // ├── .claude-plugin/marketplace.json
70
+ // └── straion-plugin/
71
+ // ├── .claude-plugin/plugin.json
72
+ // ├── skills/straion/
73
+ // └── hooks/
74
+ await cp(extractedDir, centralMarketplaceDir, { recursive: true });
75
+ progress('Skills and plugins downloaded successfully');
76
+ }
77
+ finally {
78
+ // Clean up temp directory
79
+ rmSync(tempDir, { recursive: true, force: true });
80
+ }
81
+ }
82
+ /**
83
+ * Check how skill is linked for an agent
84
+ */
85
+ export function getLinkType(agentSkillsDir) {
86
+ const skillPath = join(agentSkillsDir);
87
+ if (!existsSync(skillPath)) {
88
+ return 'none';
89
+ }
90
+ try {
91
+ const stats = lstatSync(skillPath);
92
+ if (stats.isSymbolicLink()) {
93
+ // Verify it points to our central skill
94
+ const target = readlinkSync(skillPath);
95
+ if (target === centralSkillsDir) {
96
+ return 'symlink';
97
+ }
98
+ // Symlink exists but points elsewhere
99
+ return 'none';
100
+ }
101
+ // It's a regular directory (copy)
102
+ return 'copy';
103
+ }
104
+ catch {
105
+ return 'none';
106
+ }
107
+ }
108
+ /**
109
+ * Cleans and recreates a directory.
110
+ * Handles edge cases like broken symlinks and ELOOP errors.
111
+ */
112
+ function cleanAndCreate(path) {
113
+ try {
114
+ rmSync(path, { recursive: true, force: true });
115
+ }
116
+ catch {
117
+ // Ignore cleanup errors - mkdir will fail if there's a real problem
118
+ }
119
+ mkdirSync(path, { recursive: true });
120
+ }
121
+ /**
122
+ * Link skill to agent (symlink preferred, copy as fallback)
123
+ * @returns LinkResult with success status, path, and mode
124
+ */
125
+ export async function linkSkill(agentSkillsDir, skillName) {
126
+ if (!existsSync(centralSkillsDir)) {
127
+ return {
128
+ success: false,
129
+ path: '',
130
+ type: 'skill',
131
+ mode: 'symlink',
132
+ error: 'Central skills not downloaded. Call download() first.',
133
+ };
134
+ }
135
+ // Ensure agent skills directory exists
136
+ mkdirSync(agentSkillsDir, { recursive: true });
137
+ const targetPath = join(agentSkillsDir, skillName);
138
+ const centralSkillPath = join(centralSkillsDir, skillName);
139
+ logger.debug(`Linking skill ${skillName} to agent skills dir at ${targetPath}`);
140
+ // Self-loop detection: if paths resolve to same location, no symlink needed
141
+ const resolvedSource = resolve(centralSkillPath);
142
+ const resolvedTarget = resolve(targetPath);
143
+ logger.debug({ source: resolvedSource, target: resolvedTarget }, 'Resolved paths for self-loop check');
144
+ if (resolvedSource === resolvedTarget) {
145
+ return { success: true, path: targetPath, mode: 'symlink', type: 'skill' };
146
+ }
147
+ // Clean up existing path, handling ELOOP (circular symlink) errors
148
+ try {
149
+ const stats = lstatSync(targetPath);
150
+ if (stats) {
151
+ rmSync(targetPath, { recursive: true, force: true });
152
+ }
153
+ }
154
+ catch (err) {
155
+ // Handle ELOOP (too many symbolic links) - indicates corrupted symlink
156
+ if (err && typeof err === 'object' && 'code' in err && err.code === 'ELOOP') {
157
+ try {
158
+ rmSync(targetPath, { force: true });
159
+ }
160
+ catch {
161
+ // If we can't remove it, symlink creation will fail and trigger copy fallback
162
+ }
163
+ }
164
+ // ENOENT is fine - path doesn't exist
165
+ }
166
+ // Try symlink first
167
+ try {
168
+ symlinkSync(centralSkillPath, targetPath, 'dir');
169
+ return { success: true, path: targetPath, mode: 'symlink', type: 'skill' };
170
+ }
171
+ catch {
172
+ // Symlink failed (likely Windows without dev mode), fall back to copy
173
+ try {
174
+ cleanAndCreate(targetPath);
175
+ await cp(centralSkillPath, targetPath, { recursive: true });
176
+ return { success: true, path: targetPath, mode: 'copy', type: 'skill' };
177
+ }
178
+ catch (copyErr) {
179
+ return {
180
+ success: false,
181
+ path: targetPath,
182
+ mode: 'copy',
183
+ error: copyErr instanceof Error ? copyErr.message : 'Failed to copy skills',
184
+ type: 'skill',
185
+ };
186
+ }
187
+ }
188
+ }
189
+ export async function linkPlugin(installPlugin) {
190
+ if (!existsSync(centralMarketplaceDir)) {
191
+ logger.error('Central marketplace directory does not exist.');
192
+ return {
193
+ success: false,
194
+ path: '',
195
+ mode: 'plugin',
196
+ type: 'plugin',
197
+ error: 'Plugin not downloaded. Call download() first.',
198
+ };
199
+ }
200
+ // If agent has a native plugin install method, use it
201
+ const success = await installPlugin(centralMarketplaceDir);
202
+ return {
203
+ success,
204
+ path: centralMarketplaceDir,
205
+ mode: 'plugin',
206
+ type: 'plugin',
207
+ error: success ? undefined : 'Failed to install plugin via agent CLI',
208
+ };
209
+ }
210
+ export async function link(agent) {
211
+ const agentInfo = agents[agent];
212
+ if ('installPlugin' in agentInfo) {
213
+ const res = await linkPlugin(agentInfo.installPlugin);
214
+ return [res];
215
+ }
216
+ else {
217
+ // we need to create one link per skill in the central skill directory.
218
+ const skillDirs = readdirSync(centralSkillsDir, { withFileTypes: true })
219
+ .filter((dirent) => dirent.isDirectory())
220
+ .map((dirent) => dirent.name);
221
+ const results = await Promise.allSettled(skillDirs.map((skillName) => linkSkill(agentInfo.globalSkillsDir, skillName)));
222
+ return results.map((res) => res.status === 'fulfilled'
223
+ ? res.value
224
+ : {
225
+ success: false,
226
+ path: '',
227
+ mode: 'symlink',
228
+ type: 'skill',
229
+ error: res.reason instanceof Error ? res.reason.message : String(res.reason),
230
+ });
231
+ }
232
+ }
233
+ //# sourceMappingURL=skills-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skills-manager.js","sourceRoot":"","sources":["../../src/lib/skills-manager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Unit tests for the skills-manager module.
3
+ *
4
+ * Tests cover skill download, linking (symlink/copy), and detection.
5
+ */
6
+ export {};
7
+ //# sourceMappingURL=skills-manager.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skills-manager.test.d.ts","sourceRoot":"","sources":["../../src/lib/skills-manager.test.ts"],"names":[],"mappings":"AAAA;;;;GAIG"}
@@ -0,0 +1,248 @@
1
+ /**
2
+ * Unit tests for the skills-manager module.
3
+ *
4
+ * Tests cover skill download, linking (symlink/copy), and detection.
5
+ */
6
+ import { existsSync, lstatSync, mkdirSync, readlinkSync, rmSync, symlinkSync, writeFileSync, } from 'node:fs';
7
+ import os from 'node:os';
8
+ import path from 'node:path';
9
+ import { afterAll, afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
10
+ // Use vi.hoisted to create the mock path before vi.mock runs
11
+ const { mockGlobalDir } = vi.hoisted(() => {
12
+ const nodePath = require('node:path');
13
+ const nodeOs = require('node:os');
14
+ const nodeFs = require('node:fs');
15
+ const testId = `${Date.now()}-${Math.random().toString(36).slice(2)}`;
16
+ const dir = nodePath.join(nodeOs.tmpdir(), `straion-test-global-${testId}`);
17
+ return {
18
+ mockGlobalDir: dir,
19
+ existsSync: nodeFs.existsSync,
20
+ mkdirSync: nodeFs.mkdirSync,
21
+ };
22
+ });
23
+ vi.mock('../state/global-config.js', () => {
24
+ const nodeFs = require('node:fs');
25
+ return {
26
+ globalDir: mockGlobalDir,
27
+ ensureGlobalDir: () => {
28
+ if (!nodeFs.existsSync(mockGlobalDir)) {
29
+ nodeFs.mkdirSync(mockGlobalDir, { recursive: true });
30
+ }
31
+ return mockGlobalDir;
32
+ },
33
+ };
34
+ });
35
+ // Import after mocking
36
+ import { download, getLinkType, isDownloaded, linkSkill } from './skills-manager.js';
37
+ describe('skills-manager', () => {
38
+ let tempAgentDir;
39
+ // New marketplace structure
40
+ const centralMarketplaceDir = path.join(mockGlobalDir, 'marketplace');
41
+ const centralPluginPath = path.join(centralMarketplaceDir, 'straion-plugin');
42
+ const centralSkillsDir = path.join(centralPluginPath, 'skills');
43
+ const centralSkillPath = path.join(centralSkillsDir, 'straion');
44
+ beforeEach(() => {
45
+ // Create fresh temp directories for each test
46
+ tempAgentDir = path.join(os.tmpdir(), `straion-agent-test-${Date.now()}-${Math.random().toString(36).slice(2)}`);
47
+ mkdirSync(tempAgentDir, { recursive: true });
48
+ // Ensure clean state for global dir
49
+ mkdirSync(mockGlobalDir, { recursive: true });
50
+ if (existsSync(centralMarketplaceDir)) {
51
+ rmSync(centralMarketplaceDir, { recursive: true, force: true });
52
+ }
53
+ });
54
+ afterEach(() => {
55
+ // Clean up temp directories
56
+ if (existsSync(tempAgentDir)) {
57
+ rmSync(tempAgentDir, { recursive: true, force: true });
58
+ }
59
+ if (existsSync(centralMarketplaceDir)) {
60
+ rmSync(centralMarketplaceDir, { recursive: true, force: true });
61
+ }
62
+ });
63
+ afterAll(() => {
64
+ // Clean up mock global dir
65
+ if (existsSync(mockGlobalDir)) {
66
+ rmSync(mockGlobalDir, { recursive: true, force: true });
67
+ }
68
+ });
69
+ describe('isDownloaded', () => {
70
+ it('returns false when marketplace directory does not exist', () => {
71
+ expect(isDownloaded()).toBe(false);
72
+ });
73
+ it('returns true when marketplace directory exists', () => {
74
+ mkdirSync(centralMarketplaceDir, { recursive: true });
75
+ expect(isDownloaded()).toBe(true);
76
+ });
77
+ it('returns true when marketplace and plugin directories exist', () => {
78
+ mkdirSync(centralPluginPath, { recursive: true });
79
+ expect(isDownloaded()).toBe(true);
80
+ });
81
+ });
82
+ describe('getLinkType', () => {
83
+ it('returns "none" when skill path does not exist', () => {
84
+ const skillPath = path.join(tempAgentDir, 'straion');
85
+ const result = getLinkType(skillPath);
86
+ expect(result).toBe('none');
87
+ });
88
+ it('returns "copy" when skill path is a regular directory', () => {
89
+ const skillPath = path.join(tempAgentDir, 'straion');
90
+ mkdirSync(skillPath, { recursive: true });
91
+ writeFileSync(path.join(skillPath, 'SKILL.md'), '# Test Skill');
92
+ const result = getLinkType(skillPath);
93
+ expect(result).toBe('copy');
94
+ });
95
+ it('returns "symlink" when skill path is a symlink to central path', () => {
96
+ // Create central skills directory
97
+ mkdirSync(centralSkillsDir, { recursive: true });
98
+ writeFileSync(path.join(centralSkillsDir, 'SKILL.md'), '# Central Skill');
99
+ // Create symlink in agent dir pointing to centralSkillsDir
100
+ const skillPath = path.join(tempAgentDir, 'straion');
101
+ symlinkSync(centralSkillsDir, skillPath, 'dir');
102
+ const result = getLinkType(skillPath);
103
+ expect(result).toBe('symlink');
104
+ });
105
+ it('returns "none" when symlink points to different location', () => {
106
+ // Create a different target directory
107
+ const otherDir = path.join(os.tmpdir(), `other-skill-${Date.now()}`);
108
+ mkdirSync(otherDir, { recursive: true });
109
+ try {
110
+ // Create symlink pointing elsewhere
111
+ const skillPath = path.join(tempAgentDir, 'straion');
112
+ symlinkSync(otherDir, skillPath, 'dir');
113
+ const result = getLinkType(skillPath);
114
+ expect(result).toBe('none');
115
+ }
116
+ finally {
117
+ // Cleanup
118
+ rmSync(otherDir, { recursive: true, force: true });
119
+ }
120
+ });
121
+ });
122
+ describe('linkSkill', () => {
123
+ const skillName = 'straion';
124
+ beforeEach(() => {
125
+ // Create central skill directory with content (marketplace structure)
126
+ mkdirSync(centralSkillPath, { recursive: true });
127
+ writeFileSync(path.join(centralSkillPath, 'SKILL.md'), '# Central Skill\nTest content');
128
+ writeFileSync(path.join(centralSkillPath, 'index.ts'), 'export const skill = {};');
129
+ });
130
+ it('returns error when central skills not downloaded', async () => {
131
+ // Remove central skills
132
+ rmSync(centralMarketplaceDir, { recursive: true, force: true });
133
+ const result = await linkSkill(tempAgentDir, skillName);
134
+ expect(result.success).toBe(false);
135
+ expect(result.error).toContain('Central skills not downloaded');
136
+ });
137
+ it('creates agent skills directory if it does not exist', async () => {
138
+ const newAgentDir = path.join(os.tmpdir(), `new-agent-${Date.now()}`);
139
+ try {
140
+ await linkSkill(newAgentDir, skillName);
141
+ expect(existsSync(newAgentDir)).toBe(true);
142
+ }
143
+ finally {
144
+ rmSync(newAgentDir, { recursive: true, force: true });
145
+ }
146
+ });
147
+ it('creates symlink to central skill', async () => {
148
+ const result = await linkSkill(tempAgentDir, skillName);
149
+ expect(result.success).toBe(true);
150
+ const skillPath = path.join(tempAgentDir, skillName);
151
+ expect(existsSync(skillPath)).toBe(true);
152
+ expect(result.path).toBe(skillPath);
153
+ // Check if it's a symlink
154
+ const stats = lstatSync(skillPath);
155
+ if (stats.isSymbolicLink()) {
156
+ expect(result.mode).toBe('symlink');
157
+ expect(readlinkSync(skillPath)).toBe(centralSkillPath);
158
+ }
159
+ else {
160
+ // On systems where symlink fails, it should be a copy
161
+ expect(result.mode).toBe('copy');
162
+ expect(existsSync(path.join(skillPath, 'SKILL.md'))).toBe(true);
163
+ }
164
+ });
165
+ it('removes existing skill before linking', async () => {
166
+ // Create existing skill directory
167
+ const existingSkillPath = path.join(tempAgentDir, skillName);
168
+ mkdirSync(existingSkillPath, { recursive: true });
169
+ writeFileSync(path.join(existingSkillPath, 'old-file.txt'), 'old content');
170
+ await linkSkill(tempAgentDir, skillName);
171
+ // Old file should be gone
172
+ expect(existsSync(path.join(existingSkillPath, 'old-file.txt'))).toBe(false);
173
+ // New content should exist
174
+ expect(existsSync(path.join(existingSkillPath, 'SKILL.md'))).toBe(true);
175
+ });
176
+ it('removes existing symlink before linking', async () => {
177
+ // Create existing symlink to somewhere else
178
+ const otherDir = path.join(os.tmpdir(), `other-${Date.now()}`);
179
+ mkdirSync(otherDir, { recursive: true });
180
+ try {
181
+ const existingSkillPath = path.join(tempAgentDir, skillName);
182
+ symlinkSync(otherDir, existingSkillPath, 'dir');
183
+ const result = await linkSkill(tempAgentDir, skillName);
184
+ expect(result.success).toBe(true);
185
+ // Should now point to central or be a copy
186
+ const stats = lstatSync(existingSkillPath);
187
+ if (stats.isSymbolicLink()) {
188
+ expect(readlinkSync(existingSkillPath)).toBe(centralSkillPath);
189
+ }
190
+ else {
191
+ expect(existsSync(path.join(existingSkillPath, 'SKILL.md'))).toBe(true);
192
+ }
193
+ }
194
+ finally {
195
+ // Cleanup
196
+ rmSync(otherDir, { recursive: true, force: true });
197
+ }
198
+ });
199
+ it('handles self-loop when source and target resolve to same path', async () => {
200
+ // Link to the skills directory containing central skill (simulating self-loop scenario)
201
+ const result = await linkSkill(centralSkillsDir, skillName);
202
+ // Should succeed without creating a self-referential symlink
203
+ expect(result.success).toBe(true);
204
+ expect(result.mode).toBe('symlink');
205
+ });
206
+ });
207
+ describe('download', () => {
208
+ beforeEach(() => {
209
+ vi.stubGlobal('fetch', vi.fn());
210
+ });
211
+ afterEach(() => {
212
+ vi.unstubAllGlobals();
213
+ });
214
+ it('throws error on failed fetch', async () => {
215
+ vi.mocked(fetch).mockResolvedValue({
216
+ ok: false,
217
+ status: 404,
218
+ statusText: 'Not Found',
219
+ });
220
+ await expect(download()).rejects.toThrow('Failed to download: 404 Not Found');
221
+ });
222
+ it('calls progress callback during download', async () => {
223
+ vi.mocked(fetch).mockResolvedValue({
224
+ ok: true,
225
+ arrayBuffer: () => Promise.resolve(new ArrayBuffer(0)),
226
+ });
227
+ const progressMessages = [];
228
+ const onProgress = (msg) => progressMessages.push(msg);
229
+ try {
230
+ await download(onProgress);
231
+ }
232
+ catch {
233
+ // May fail on tar extraction, but progress should still be called
234
+ }
235
+ expect(progressMessages).toContain('Fetching marketplace from GitHub...');
236
+ });
237
+ it('works without progress callback', async () => {
238
+ vi.mocked(fetch).mockResolvedValue({
239
+ ok: false,
240
+ status: 500,
241
+ statusText: 'Server Error',
242
+ });
243
+ // Should not throw on missing callback, only on fetch error
244
+ await expect(download()).rejects.toThrow('Failed to download: 500 Server Error');
245
+ });
246
+ });
247
+ });
248
+ //# sourceMappingURL=skills-manager.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skills-manager.test.js","sourceRoot":"","sources":["../../src/lib/skills-manager.test.ts"],"names":[],"mappings":"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"}