@kodycodes/cli 1.26.2 → 1.26.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 (270) hide show
  1. package/dist/auth-4FW6GCLG.js +26 -0
  2. package/dist/auth-4FW6GCLG.js.map +6 -0
  3. package/dist/bin.js +27 -3
  4. package/dist/bin.js.map +6 -1
  5. package/dist/chunk-46IJPEID.js +30 -0
  6. package/dist/chunk-46IJPEID.js.map +6 -0
  7. package/dist/chunk-4D6ORNXY.js +24404 -0
  8. package/dist/chunk-4D6ORNXY.js.map +6 -0
  9. package/dist/chunk-64IM6G4Z.js +341 -0
  10. package/dist/chunk-64IM6G4Z.js.map +6 -0
  11. package/dist/{package-local-runtime-source.js → chunk-64XN367G.js} +373 -52
  12. package/dist/chunk-64XN367G.js.map +6 -0
  13. package/dist/chunk-6XQP5SWX.js +26 -0
  14. package/dist/chunk-6XQP5SWX.js.map +6 -0
  15. package/dist/chunk-75RZUXQL.js +62 -0
  16. package/dist/chunk-75RZUXQL.js.map +6 -0
  17. package/dist/chunk-BISUL7CE.js +106 -0
  18. package/dist/chunk-BISUL7CE.js.map +6 -0
  19. package/dist/chunk-BPGY4IE7.js +57 -0
  20. package/dist/chunk-BPGY4IE7.js.map +6 -0
  21. package/dist/chunk-CASGRYOF.js +21 -0
  22. package/dist/chunk-CASGRYOF.js.map +6 -0
  23. package/dist/chunk-CWWHR4FH.js +19 -0
  24. package/dist/chunk-CWWHR4FH.js.map +6 -0
  25. package/dist/chunk-D55XPY3T.js +1382 -0
  26. package/dist/chunk-D55XPY3T.js.map +6 -0
  27. package/dist/chunk-EOCV74B2.js +948 -0
  28. package/dist/chunk-EOCV74B2.js.map +6 -0
  29. package/dist/chunk-FBVNFWR6.js +437 -0
  30. package/dist/chunk-FBVNFWR6.js.map +6 -0
  31. package/dist/chunk-G4YN6XP5.js +14 -0
  32. package/dist/chunk-G4YN6XP5.js.map +6 -0
  33. package/dist/chunk-G6LJWROP.js +18 -0
  34. package/dist/chunk-G6LJWROP.js.map +6 -0
  35. package/dist/chunk-IHP6PV6X.js +49 -0
  36. package/dist/chunk-IHP6PV6X.js.map +6 -0
  37. package/dist/chunk-JWEFKKAD.js +24 -0
  38. package/dist/chunk-JWEFKKAD.js.map +6 -0
  39. package/dist/chunk-LWNB26KO.js +147 -0
  40. package/dist/chunk-LWNB26KO.js.map +6 -0
  41. package/dist/chunk-OVGXPRSY.js +20 -0
  42. package/dist/chunk-OVGXPRSY.js.map +6 -0
  43. package/dist/chunk-PDWCKWQF.js +453 -0
  44. package/dist/chunk-PDWCKWQF.js.map +6 -0
  45. package/dist/chunk-QHBCP4OB.js +44 -0
  46. package/dist/chunk-QHBCP4OB.js.map +6 -0
  47. package/dist/chunk-R4IUV5P5.js +664 -0
  48. package/dist/chunk-R4IUV5P5.js.map +6 -0
  49. package/dist/chunk-RM34N3KI.js +525 -0
  50. package/dist/chunk-RM34N3KI.js.map +6 -0
  51. package/dist/chunk-RTWUNV76.js +309 -0
  52. package/dist/chunk-RTWUNV76.js.map +6 -0
  53. package/dist/chunk-SMURF26I.js +23 -0
  54. package/dist/chunk-SMURF26I.js.map +6 -0
  55. package/dist/chunk-SXHULGL4.js +426 -0
  56. package/dist/chunk-SXHULGL4.js.map +6 -0
  57. package/dist/chunk-TIL35OWA.js +1959 -0
  58. package/dist/chunk-TIL35OWA.js.map +6 -0
  59. package/dist/chunk-VQS5YSCI.js +54 -0
  60. package/dist/chunk-VQS5YSCI.js.map +6 -0
  61. package/dist/chunk-XDCOWU5R.js +696 -0
  62. package/dist/chunk-XDCOWU5R.js.map +6 -0
  63. package/dist/chunk-XOPPGRUP.js +605 -0
  64. package/dist/chunk-XOPPGRUP.js.map +6 -0
  65. package/dist/cli.js +74 -1500
  66. package/dist/cli.js.map +6 -1
  67. package/dist/dev-command-3LX234N6.js +4900 -0
  68. package/dist/dev-command-3LX234N6.js.map +6 -0
  69. package/dist/git-credential-FUE3JE3T.js +163 -0
  70. package/dist/git-credential-FUE3JE3T.js.map +6 -0
  71. package/dist/install-ZML2TCDG.js +10694 -0
  72. package/dist/install-ZML2TCDG.js.map +6 -0
  73. package/dist/local-execute-SZV6XN4T.js +368 -0
  74. package/dist/local-execute-SZV6XN4T.js.map +6 -0
  75. package/dist/local-package-run-2TMCAZZ2.js +23 -0
  76. package/dist/local-package-run-2TMCAZZ2.js.map +6 -0
  77. package/dist/mcp-G2AWTIXR.js +21 -0
  78. package/dist/mcp-G2AWTIXR.js.map +6 -0
  79. package/dist/mock-dep-resolve-TVABDNR7.js +52 -0
  80. package/dist/mock-dep-resolve-TVABDNR7.js.map +6 -0
  81. package/dist/mock-fetch-gateway-B5TFGGQS.js +34 -0
  82. package/dist/mock-fetch-gateway-B5TFGGQS.js.map +6 -0
  83. package/dist/mock-local-deps-5SZT3PWT.js +197 -0
  84. package/dist/mock-local-deps-5SZT3PWT.js.map +6 -0
  85. package/dist/mock-server-SV2IKC4I.js +21 -0
  86. package/dist/mock-server-SV2IKC4I.js.map +6 -0
  87. package/dist/open-api-client-DVVMLY7P.js +42 -0
  88. package/dist/open-api-client-DVVMLY7P.js.map +6 -0
  89. package/dist/org-X7B5BI4R.js +132 -0
  90. package/dist/org-X7B5BI4R.js.map +6 -0
  91. package/dist/package-manifest-QH2RU64C.js +14 -0
  92. package/dist/package-manifest-QH2RU64C.js.map +6 -0
  93. package/dist/remote-execute-QMQDVHOY.js +110 -0
  94. package/dist/remote-execute-QMQDVHOY.js.map +6 -0
  95. package/dist/setup-git-5KCUBYPB.js +88 -0
  96. package/dist/setup-git-5KCUBYPB.js.map +6 -0
  97. package/dist/skill-ENPATRIW.js +43 -0
  98. package/dist/skill-ENPATRIW.js.map +6 -0
  99. package/dist/store-WTMRH527.js +48 -0
  100. package/dist/store-WTMRH527.js.map +6 -0
  101. package/dist/structured-error-C65GQ53Z.js +13 -0
  102. package/dist/structured-error-C65GQ53Z.js.map +6 -0
  103. package/dist/target-3QHY7JT4.js +45 -0
  104. package/dist/target-3QHY7JT4.js.map +6 -0
  105. package/dist/webapi-NTVP4BO3.js +2482 -0
  106. package/dist/webapi-NTVP4BO3.js.map +6 -0
  107. package/package.json +8 -8
  108. package/dist/add-mcp-install.js +0 -59
  109. package/dist/add-mcp-install.js.map +0 -1
  110. package/dist/api-token-store.js +0 -120
  111. package/dist/api-token-store.js.map +0 -1
  112. package/dist/api-token.js +0 -238
  113. package/dist/api-token.js.map +0 -1
  114. package/dist/auth-bootstrap.js +0 -373
  115. package/dist/auth-bootstrap.js.map +0 -1
  116. package/dist/auth.js +0 -386
  117. package/dist/auth.js.map +0 -1
  118. package/dist/capability-proxy.js +0 -527
  119. package/dist/capability-proxy.js.map +0 -1
  120. package/dist/credential-call-map.js +0 -155
  121. package/dist/credential-call-map.js.map +0 -1
  122. package/dist/credential-client-runtime-source.js +0 -9
  123. package/dist/credential-client-runtime-source.js.map +0 -1
  124. package/dist/credentialed-fetch-scan.js +0 -98
  125. package/dist/credentialed-fetch-scan.js.map +0 -1
  126. package/dist/defaults.js +0 -34
  127. package/dist/defaults.js.map +0 -1
  128. package/dist/detect-running-hosts.js +0 -13
  129. package/dist/detect-running-hosts.js.map +0 -1
  130. package/dist/dev/dev-assets.js +0 -202
  131. package/dist/dev/dev-assets.js.map +0 -1
  132. package/dist/dev/dev-bundler.js +0 -65
  133. package/dist/dev/dev-bundler.js.map +0 -1
  134. package/dist/dev/dev-events.js +0 -94
  135. package/dist/dev/dev-events.js.map +0 -1
  136. package/dist/dev/dev-port.js +0 -80
  137. package/dist/dev/dev-port.js.map +0 -1
  138. package/dist/dev/dev-protocol.js +0 -14
  139. package/dist/dev/dev-protocol.js.map +0 -1
  140. package/dist/dev/dev-registry.js +0 -95
  141. package/dist/dev/dev-registry.js.map +0 -1
  142. package/dist/dev/dev-watcher.js +0 -162
  143. package/dist/dev/dev-watcher.js.map +0 -1
  144. package/dist/dev/error-page.js +0 -64
  145. package/dist/dev/error-page.js.map +0 -1
  146. package/dist/dev/live-reload.js +0 -151
  147. package/dist/dev/live-reload.js.map +0 -1
  148. package/dist/dev/prebuild.js +0 -102
  149. package/dist/dev/prebuild.js.map +0 -1
  150. package/dist/dev/process-reaper.js +0 -151
  151. package/dist/dev/process-reaper.js.map +0 -1
  152. package/dist/dev/stack-trace.js +0 -56
  153. package/dist/dev/stack-trace.js.map +0 -1
  154. package/dist/dev/workerd-process.js +0 -118
  155. package/dist/dev/workerd-process.js.map +0 -1
  156. package/dist/dev-command.js +0 -676
  157. package/dist/dev-command.js.map +0 -1
  158. package/dist/discover-login-identity.js +0 -77
  159. package/dist/discover-login-identity.js.map +0 -1
  160. package/dist/discover-org.js +0 -62
  161. package/dist/discover-org.js.map +0 -1
  162. package/dist/git-credential.js +0 -147
  163. package/dist/git-credential.js.map +0 -1
  164. package/dist/help.js +0 -333
  165. package/dist/help.js.map +0 -1
  166. package/dist/host-catalog.js +0 -427
  167. package/dist/host-catalog.js.map +0 -1
  168. package/dist/host-config.js +0 -80
  169. package/dist/host-config.js.map +0 -1
  170. package/dist/http-error-body.js +0 -35
  171. package/dist/http-error-body.js.map +0 -1
  172. package/dist/install-hosts.js +0 -328
  173. package/dist/install-hosts.js.map +0 -1
  174. package/dist/install.js +0 -120
  175. package/dist/install.js.map +0 -1
  176. package/dist/invoke-passthrough.js +0 -60
  177. package/dist/invoke-passthrough.js.map +0 -1
  178. package/dist/local-bundle.js +0 -200
  179. package/dist/local-bundle.js.map +0 -1
  180. package/dist/local-execute-auth.js +0 -53
  181. package/dist/local-execute-auth.js.map +0 -1
  182. package/dist/local-execute.js +0 -338
  183. package/dist/local-execute.js.map +0 -1
  184. package/dist/local-gateway-fetch-forward.js +0 -135
  185. package/dist/local-gateway-fetch-forward.js.map +0 -1
  186. package/dist/local-host-runtime-surface.js +0 -75
  187. package/dist/local-host-runtime-surface.js.map +0 -1
  188. package/dist/local-package-graph.js +0 -405
  189. package/dist/local-package-graph.js.map +0 -1
  190. package/dist/local-package-run.js +0 -307
  191. package/dist/local-package-run.js.map +0 -1
  192. package/dist/local-runtime-bridge.js +0 -132
  193. package/dist/local-runtime-bridge.js.map +0 -1
  194. package/dist/local-runtime-source.js +0 -541
  195. package/dist/local-runtime-source.js.map +0 -1
  196. package/dist/login-callback-assets.js +0 -10
  197. package/dist/login-callback-assets.js.map +0 -1
  198. package/dist/login-callback-page.js +0 -362
  199. package/dist/login-callback-page.js.map +0 -1
  200. package/dist/mcp.js +0 -134
  201. package/dist/mcp.js.map +0 -1
  202. package/dist/mock/ensure-msw.js +0 -215
  203. package/dist/mock/ensure-msw.js.map +0 -1
  204. package/dist/mock/install-mock-fetch-shim.js +0 -36
  205. package/dist/mock/install-mock-fetch-shim.js.map +0 -1
  206. package/dist/mock/load-package-mocks.js +0 -136
  207. package/dist/mock/load-package-mocks.js.map +0 -1
  208. package/dist/mock/mock-fetch-gateway.js +0 -343
  209. package/dist/mock/mock-fetch-gateway.js.map +0 -1
  210. package/dist/mock/mock-gateway-fetch-shim.js +0 -104
  211. package/dist/mock/mock-gateway-fetch-shim.js.map +0 -1
  212. package/dist/mock/mock-server.js +0 -499
  213. package/dist/mock/mock-server.js.map +0 -1
  214. package/dist/mock/mock-storage.js +0 -186
  215. package/dist/mock/mock-storage.js.map +0 -1
  216. package/dist/mock/mock-supported.js +0 -63
  217. package/dist/mock/mock-supported.js.map +0 -1
  218. package/dist/mock-dep-resolve.js +0 -47
  219. package/dist/mock-dep-resolve.js.map +0 -1
  220. package/dist/mock-local-deps.js +0 -207
  221. package/dist/mock-local-deps.js.map +0 -1
  222. package/dist/network-error.js +0 -11
  223. package/dist/network-error.js.map +0 -1
  224. package/dist/node-engine.js +0 -21
  225. package/dist/node-engine.js.map +0 -1
  226. package/dist/oauth-provider.js +0 -107
  227. package/dist/oauth-provider.js.map +0 -1
  228. package/dist/onboarding-prompt.js +0 -15
  229. package/dist/onboarding-prompt.js.map +0 -1
  230. package/dist/open-api-client.js +0 -432
  231. package/dist/open-api-client.js.map +0 -1
  232. package/dist/open-url.js +0 -21
  233. package/dist/open-url.js.map +0 -1
  234. package/dist/org-resolve.js +0 -16
  235. package/dist/org-resolve.js.map +0 -1
  236. package/dist/org-slug.js +0 -11
  237. package/dist/org-slug.js.map +0 -1
  238. package/dist/org.js +0 -100
  239. package/dist/org.js.map +0 -1
  240. package/dist/package-app-dev.js +0 -922
  241. package/dist/package-app-dev.js.map +0 -1
  242. package/dist/package-collaborators.js +0 -179
  243. package/dist/package-collaborators.js.map +0 -1
  244. package/dist/package-info.js +0 -19
  245. package/dist/package-info.js.map +0 -1
  246. package/dist/package-local-runtime-source.js.map +0 -1
  247. package/dist/package-manifest.js +0 -364
  248. package/dist/package-manifest.js.map +0 -1
  249. package/dist/process-info.js +0 -14
  250. package/dist/process-info.js.map +0 -1
  251. package/dist/redact.js +0 -16
  252. package/dist/redact.js.map +0 -1
  253. package/dist/remote-execute.js +0 -108
  254. package/dist/remote-execute.js.map +0 -1
  255. package/dist/setup-git.js +0 -676
  256. package/dist/setup-git.js.map +0 -1
  257. package/dist/skill.js +0 -35
  258. package/dist/skill.js.map +0 -1
  259. package/dist/store.js +0 -597
  260. package/dist/store.js.map +0 -1
  261. package/dist/structured-error.js +0 -57
  262. package/dist/structured-error.js.map +0 -1
  263. package/dist/target.js +0 -52
  264. package/dist/target.js.map +0 -1
  265. package/dist/tool-result.js +0 -19
  266. package/dist/tool-result.js.map +0 -1
  267. package/dist/which.js +0 -22
  268. package/dist/which.js.map +0 -1
  269. package/dist/workerd-binary.js +0 -98
  270. package/dist/workerd-binary.js.map +0 -1
package/dist/setup-git.js DELETED
@@ -1,676 +0,0 @@
1
- import { spawnSync } from 'node:child_process';
2
- import { createRequire } from 'node:module';
3
- import { apiTokenEnvVar, cliName, defaultApiUrl, defaultMcpUrl, } from './defaults.js';
4
- import { authBootstrapWithScopes, cliTokenLifetimeAliases, resolveCliTokenLifetime, } from './auth-bootstrap.js';
5
- import { deleteStoredApiToken, loadStoredApiToken, } from './api-token-store.js';
6
- import { OpenApiError, openApiGet, openApiRequest } from './open-api-client.js';
7
- import { which as whichOnPath } from './which.js';
8
- /** Scopes setup-git always requires for clone/fetch (+ push). */
9
- export const setupGitRequiredScopes = ['package:read', 'package:write'];
10
- /**
11
- * Default mint list when setup-git needs a fresh token: CLI bootstrap defaults
12
- * plus the package scopes git HTTPS needs. Callers can replace via `--scopes`.
13
- */
14
- export const setupGitDefaultScopes = [
15
- 'app:execute',
16
- 'app:read',
17
- 'email:read',
18
- 'email:send',
19
- 'integration:read',
20
- 'integration:use',
21
- 'job:execute',
22
- 'job:read',
23
- 'memory:read',
24
- 'org:execute',
25
- 'org:read',
26
- 'package:execute',
27
- 'package:read',
28
- 'package:write',
29
- 'secret:use',
30
- 'token:delete',
31
- ];
32
- /**
33
- * Origin host for `credential.https://<host>.*` (guide: `kody.codes`).
34
- * Derived from the MCP URL origin so preview / self-host installs match.
35
- */
36
- export function gitCredentialHostFromMcpUrl(mcpUrl = defaultMcpUrl) {
37
- return new URL(mcpUrl).host;
38
- }
39
- export function scopesIncludeRequired(scopes, required = setupGitRequiredScopes) {
40
- if (!scopes)
41
- return false;
42
- const held = new Set(scopes);
43
- return required.every((scope) => held.has(scope));
44
- }
45
- /** Ensure package:read/write are present; preserve order of the base list. */
46
- export function ensureSetupGitScopes(base = setupGitDefaultScopes) {
47
- const out = [...base];
48
- for (const required of setupGitRequiredScopes) {
49
- if (!out.includes(required))
50
- out.push(required);
51
- }
52
- return out;
53
- }
54
- export async function fetchTokenCurrentMetadata(input) {
55
- const apiUrl = input.apiUrl || defaultApiUrl;
56
- const current = (await openApiGet({
57
- token: input.token,
58
- apiUrl,
59
- path: 'v1/tokens/current',
60
- fetchFn: input.fetchFn,
61
- }));
62
- const orgBindingRaw = current.org_binding;
63
- const orgBinding = orgBindingRaw === 'user' || orgBindingRaw === 'org' ? orgBindingRaw : null;
64
- return {
65
- id: String(current.id ?? ''),
66
- orgBinding,
67
- scopes: Array.isArray(current.scopes)
68
- ? current.scopes.filter((scope) => typeof scope === 'string')
69
- : [],
70
- expiresAt: typeof current.expires_at === 'string' ? current.expires_at : null,
71
- };
72
- }
73
- /**
74
- * User-owned tokens (and the git helper) require `org_binding` on token
75
- * metadata. Older origins omit the field — refuse rather than install a
76
- * broken helper.
77
- */
78
- export function assertUserOwnedTokensLive(metadata) {
79
- if (metadata.orgBinding === null) {
80
- throw new Error('This Kody origin does not advertise user-owned API tokens (`org_binding` missing on GET /v1/tokens/current). Upgrade the server (kody auth setup-git / persistent git HTTPS) before installing the credential helper.');
81
- }
82
- }
83
- /**
84
- * Reuse a stored user-owned token that already has package:read/write; otherwise
85
- * mint a long-lived user-owned token with those scopes.
86
- */
87
- export function decideSetupGitToken(input) {
88
- const lifetime = input.lifetime ??
89
- resolveCliTokenLifetime({ lifetime: 'long' });
90
- if (input.stored &&
91
- input.metadata &&
92
- input.metadata.orgBinding === 'user' &&
93
- scopesIncludeRequired(input.metadata.scopes) &&
94
- !input.scopesOverride) {
95
- return { action: 'reuse', stored: input.stored, metadata: input.metadata };
96
- }
97
- // Prefer extending the current token's scopes so a parent API token can
98
- // mint them; fall back to the setup-git default list for a blank slate.
99
- const scopes = ensureSetupGitScopes(input.scopesOverride ??
100
- input.metadata?.scopes ??
101
- input.stored?.scopes ??
102
- setupGitDefaultScopes);
103
- const reason = !input.stored
104
- ? 'No stored API token yet.'
105
- : input.metadata?.orgBinding !== 'user'
106
- ? 'Stored token is not user-owned (`org_binding` must be `user`).'
107
- : !scopesIncludeRequired(input.metadata?.scopes)
108
- ? 'Stored token is missing package:read and/or package:write.'
109
- : 'Minting with the requested --scopes list.';
110
- return { action: 'mint', scopes, lifetime, reason };
111
- }
112
- export function defaultGitConfigRunner(args) {
113
- const result = spawnSync('git', [...args], {
114
- encoding: 'utf8',
115
- env: process.env,
116
- });
117
- if (result.error) {
118
- return { status: 1, stderr: result.error.message };
119
- }
120
- return {
121
- status: result.status ?? 1,
122
- stderr: (result.stderr || '').trim(),
123
- };
124
- }
125
- /**
126
- * Install URL-scoped credential helper config from the server contract:
127
- * `credential.https://<host>.helper` and `.useHttpPath true`.
128
- */
129
- export function installGitCredentialConfig(input) {
130
- const runGit = input.runGit ?? defaultGitConfigRunner;
131
- const scope = input.global === false ? '--local' : '--global';
132
- const helperKey = `credential.https://${input.host}.helper`;
133
- const pathKey = `credential.https://${input.host}.useHttpPath`;
134
- for (const [key, value] of [
135
- [helperKey, input.helperCommand],
136
- [pathKey, 'true'],
137
- ]) {
138
- const result = runGit(['config', scope, key, value]);
139
- if (result.status !== 0) {
140
- throw new Error(`git config ${scope} ${key} failed${result.stderr ? `: ${result.stderr}` : ''}. Is git installed?`);
141
- }
142
- }
143
- return { host: input.host, helperCommand: input.helperCommand, scope };
144
- }
145
- /** Refresh git HTTPS tokens this long before `expiresAt` (or when past it). */
146
- export const gitApiTokenRefreshSkewMs = 60 * 60 * 1000;
147
- /**
148
- * First published CLI line that includes `git-credential` / `auth setup-git`.
149
- * Global installs older than this must not be preferred as the helper binary.
150
- */
151
- export const gitCredentialMinCliVersion = '1.16.0';
152
- /**
153
- * Fallback exact pin for local `0.0.0-semantically-released` builds. Published
154
- * tarballs always carry a real x.y.z from semantic-release. Keep this at a
155
- * recent published line that includes `git-credential` (not merely the
156
- * minimum) so local/dev pins are not stuck on an ancient helper.
157
- */
158
- export const gitCredentialHelperPinFallbackVersion = '1.18.0';
159
- const requireFromSetupGit = createRequire(import.meta.url);
160
- export function readCliPackageVersion() {
161
- try {
162
- const pkg = requireFromSetupGit('../package.json');
163
- return typeof pkg.version === 'string' ? pkg.version : gitCredentialHelperPinFallbackVersion;
164
- }
165
- catch {
166
- return gitCredentialHelperPinFallbackVersion;
167
- }
168
- }
169
- /**
170
- * True when the CLI entry lives under npm's ephemeral `npx` cache
171
- * (`~/.npm/_npx/…`). Those paths break after `npm cache clean`.
172
- */
173
- export function isEphemeralNpxEntryPath(entryPath) {
174
- const normalized = entryPath.replace(/\\/g, '/');
175
- return (normalized.includes('/.npm/_npx/') ||
176
- normalized.includes('/npm/_npx/') ||
177
- /\/_npx\//.test(normalized));
178
- }
179
- /** Parse a leading `x.y.z` from a CLI version string (ignores prerelease tags). */
180
- export function parseCliSemver(version) {
181
- const match = /^(\d+)\.(\d+)\.(\d+)/.exec(version.trim());
182
- if (!match)
183
- return null;
184
- return {
185
- major: Number(match[1]),
186
- minor: Number(match[2]),
187
- patch: Number(match[3]),
188
- };
189
- }
190
- export function compareCliSemver(a, b) {
191
- if (a.major !== b.major)
192
- return a.major < b.major ? -1 : 1;
193
- if (a.minor !== b.minor)
194
- return a.minor < b.minor ? -1 : 1;
195
- if (a.patch !== b.patch)
196
- return a.patch < b.patch ? -1 : 1;
197
- return 0;
198
- }
199
- export function cliVersionGte(version, minimum) {
200
- const left = parseCliSemver(version);
201
- const right = parseCliSemver(minimum);
202
- if (!left || !right)
203
- return false;
204
- return compareCliSemver(left, right) >= 0;
205
- }
206
- export function cliVersionGt(version, other) {
207
- const left = parseCliSemver(version);
208
- const right = parseCliSemver(other);
209
- if (!left || !right)
210
- return false;
211
- return compareCliSemver(left, right) > 0;
212
- }
213
- /** True when this CLI version knows the `git-credential` command. */
214
- export function cliVersionSupportsGitCredential(version) {
215
- return cliVersionGte(version, gitCredentialMinCliVersion);
216
- }
217
- /**
218
- * Exact version for `npx -y @kodycodes/cli@<x.y.z>`. Major-only ranges are
219
- * unsafe: npx can reuse a stale cache (e.g. 1.1.0 for `@1`). Local
220
- * `0.0.0-semantically-released` builds fall back to
221
- * {@link gitCredentialHelperPinFallbackVersion}.
222
- */
223
- export function cliExactVersionForNpx(packageVersion) {
224
- const parsed = parseCliSemver(packageVersion);
225
- if (parsed && parsed.major >= 1) {
226
- return `${parsed.major}.${parsed.minor}.${parsed.patch}`;
227
- }
228
- return gitCredentialHelperPinFallbackVersion;
229
- }
230
- /** @deprecated Use {@link cliExactVersionForNpx}. Kept for one release as alias. */
231
- export function cliMajorVersionForNpx(packageVersion) {
232
- return cliExactVersionForNpx(packageVersion);
233
- }
234
- /** Whether a stored API token should be reminted for git HTTPS. */
235
- export function apiTokenNeedsRefresh(stored, nowMs = Date.now(), skewMs = gitApiTokenRefreshSkewMs) {
236
- if (!stored)
237
- return true;
238
- if (stored.expiresAt == null || stored.expiresAt === '')
239
- return false;
240
- const expiresMs = Date.parse(stored.expiresAt);
241
- if (!Number.isFinite(expiresMs))
242
- return true;
243
- return expiresMs - nowMs <= skewMs;
244
- }
245
- /**
246
- * Read `kody --version` (or `node entry --version`) stdout. Returns null on
247
- * failure so callers can skip preferring an unverifiable binary.
248
- *
249
- * Always sets `KODY_SKIP_GIT_HELPER_REFRESH=1` so a nested CLI does not re-enter
250
- * pin refresh (which itself may spawn `--version` — an 8s recursive stall).
251
- */
252
- export function readVersionFromKodyBinary(binPath, args = ['--version']) {
253
- const result = spawnSync(binPath, [...args], {
254
- encoding: 'utf8',
255
- env: {
256
- ...process.env,
257
- KODY_SKIP_GIT_HELPER_REFRESH: '1',
258
- },
259
- timeout: 8_000,
260
- });
261
- if (result.error || (result.status ?? 1) !== 0)
262
- return null;
263
- const text = `${result.stdout || ''}\n${result.stderr || ''}`;
264
- const match = /(\d+\.\d+\.\d+)/.exec(text);
265
- return match?.[1] ?? null;
266
- }
267
- function defaultReadGlobalKodyVersion(binPath) {
268
- return readVersionFromKodyBinary(binPath);
269
- }
270
- /**
271
- * Helper argv for git config. Prefer a global `kody` only when its version
272
- * supports `git-credential`; else a non-npx entry path; else
273
- * `npx -y @kodycodes/cli@<exact>` so npx cannot reuse a stale major-range
274
- * cache. Re-running `auth setup-git` (and every CLI command via pin refresh)
275
- * rewrites ephemeral / major-range / outdated pins.
276
- */
277
- export function gitCredentialHelperCommand(input) {
278
- const env = input?.env ?? process.env;
279
- const whichFn = input?.which ?? whichOnPath;
280
- const entryPath = input?.entryPath ?? process.argv[1];
281
- const readVersion = input?.readKodyVersion ?? defaultReadGlobalKodyVersion;
282
- const globalKody = whichFn('kody', env);
283
- if (globalKody && !isEphemeralNpxEntryPath(globalKody)) {
284
- const globalVersion = readVersion(globalKody);
285
- if (globalVersion && cliVersionSupportsGitCredential(globalVersion)) {
286
- return `!${shellQuote(globalKody)} git-credential`;
287
- }
288
- }
289
- if (entryPath && entryPath.length > 0 && !isEphemeralNpxEntryPath(entryPath)) {
290
- const execPath = input?.execPath ?? process.execPath;
291
- return `!${shellQuote(execPath)} ${shellQuote(entryPath)} git-credential`;
292
- }
293
- const exact = cliExactVersionForNpx(input?.packageVersion ?? readCliPackageVersion());
294
- return `!npx -y ${cliName}@${exact} git-credential`;
295
- }
296
- function shellQuote(value) {
297
- if (/^[A-Za-z0-9_./:@+=,-]+$/.test(value))
298
- return value;
299
- return `'${value.replace(/'/g, `'\\''`)}'`;
300
- }
301
- /** Detect major-only npx pins (`@1`, `@2`) that can resolve to a stale cache. */
302
- export function isMajorOnlyNpxHelper(helper) {
303
- return /@kodycodes\/cli@\d+(?![\.\d])/.test(helper);
304
- }
305
- /** Exact `@kodycodes/cli@x.y.z` pin from a helper command, if present. */
306
- export function exactNpxHelperVersion(helper) {
307
- const match = /@kodycodes\/cli@(\d+\.\d+\.\d+)/.exec(helper);
308
- return match?.[1] ?? null;
309
- }
310
- /**
311
- * True when an installed helper should be rewritten: ephemeral npx path,
312
- * major-only pin, exact pin older than the running CLI, or (when probing) a
313
- * binary that does not support `git-credential`.
314
- *
315
- * Hot-path refresh (`probeBinaryVersion: false`, the default) only uses
316
- * string heuristics — never spawns `kody --version`. Binary probes stay for
317
- * `auth setup-git` so we do not pay 8s+ on every CLI / git-credential call.
318
- */
319
- export function gitCredentialHelperNeedsRepair(input) {
320
- const helper = input.helper?.trim();
321
- if (!helper)
322
- return false;
323
- if (isEphemeralNpxEntryPath(helper))
324
- return true;
325
- if (isMajorOnlyNpxHelper(helper))
326
- return true;
327
- const pinned = exactNpxHelperVersion(helper);
328
- if (pinned) {
329
- if (!cliVersionSupportsGitCredential(pinned))
330
- return true;
331
- const current = cliExactVersionForNpx(input.packageVersion ?? readCliPackageVersion());
332
- return cliVersionGt(current, pinned);
333
- }
334
- if (input.probeBinaryVersion !== true) {
335
- // Path-based helpers (`!kody git-credential` / `!node … git-credential`)
336
- // are left alone on the hot path — spawning --version here was the
337
- // 8–20s stall (and could recurse into pin refresh).
338
- return false;
339
- }
340
- // `!/path/to/kody git-credential` or `!node /path/to/bin.js git-credential`
341
- const readVersion = input.readKodyVersion ?? defaultReadGlobalKodyVersion;
342
- const bang = helper.startsWith('!') ? helper.slice(1).trim() : helper.trim();
343
- const parts = bang.split(/\s+/).filter(Boolean);
344
- if (parts.length >= 2 && parts[parts.length - 1] === 'git-credential') {
345
- const invocation = parts.slice(0, -1);
346
- if (invocation.length === 1) {
347
- const version = readVersion(invocation[0]);
348
- if (version && !cliVersionSupportsGitCredential(version))
349
- return true;
350
- }
351
- else if (invocation.length >= 2) {
352
- const version = readVersionFromKodyBinary(invocation[0], [
353
- ...invocation.slice(1),
354
- '--version',
355
- ]);
356
- if (version && !cliVersionSupportsGitCredential(version))
357
- return true;
358
- }
359
- }
360
- return false;
361
- }
362
- export function defaultGitConfigGetRunner(args) {
363
- const result = spawnSync('git', [...args], {
364
- encoding: 'utf8',
365
- env: process.env,
366
- });
367
- if (result.error) {
368
- return { status: 1, stdout: '', stderr: result.error.message };
369
- }
370
- return {
371
- status: result.status ?? 1,
372
- stdout: (result.stdout || '').trim(),
373
- stderr: (result.stderr || '').trim(),
374
- };
375
- }
376
- /**
377
- * Best-effort: if a Kody HTTPS credential helper is installed but stale,
378
- * rewrite it to {@link gitCredentialHelperCommand}. Silent — safe to call
379
- * from every CLI entry including `git-credential` (must not touch stdout).
380
- * Returns whether a rewrite ran.
381
- */
382
- export function refreshGitCredentialHelperPinIfNeeded(input) {
383
- const mcpUrl = input?.mcpUrl || defaultMcpUrl;
384
- const host = gitCredentialHostFromMcpUrl(mcpUrl);
385
- const scope = input?.global === false ? '--local' : '--global';
386
- const runGet = input?.runGitGet ?? defaultGitConfigGetRunner;
387
- const helperKey = `credential.https://${host}.helper`;
388
- const got = runGet(['config', scope, '--get', helperKey]);
389
- if (got.status !== 0 || !got.stdout)
390
- return false;
391
- const packageVersion = input?.packageVersion ?? readCliPackageVersion();
392
- if (!gitCredentialHelperNeedsRepair({
393
- helper: got.stdout,
394
- packageVersion,
395
- readKodyVersion: input?.readKodyVersion,
396
- probeBinaryVersion: input?.probeBinaryVersion === true,
397
- })) {
398
- return false;
399
- }
400
- const helperCommand = input?.helperCommand ??
401
- gitCredentialHelperCommand({
402
- packageVersion,
403
- which: input?.which,
404
- execPath: input?.execPath,
405
- entryPath: input?.entryPath,
406
- env: input?.env,
407
- readKodyVersion: input?.readKodyVersion,
408
- });
409
- if (helperCommand === got.stdout)
410
- return false;
411
- installGitCredentialConfig({
412
- host,
413
- helperCommand,
414
- global: input?.global,
415
- runGit: input?.runGit,
416
- });
417
- return true;
418
- }
419
- export async function authSetupGit(input) {
420
- const apiUrl = input.apiUrl || defaultApiUrl;
421
- const mcpUrl = input.mcpUrl || defaultMcpUrl;
422
- const host = gitCredentialHostFromMcpUrl(mcpUrl);
423
- const storedExisting = loadStoredApiToken(apiUrl, input.backend, input.resolution);
424
- const probeToken = input.token || storedExisting?.token;
425
- const hasLoginSession = input.hasLoginSession === true;
426
- if (!probeToken && !hasLoginSession) {
427
- throw new Error(`setup-git needs a Kody credential to detect server support and mint a token. Run \`kody login\`, or set ${apiTokenEnvVar}, or pass --token.`);
428
- }
429
- let probeMetadata = null;
430
- if (probeToken) {
431
- try {
432
- probeMetadata = await fetchTokenCurrentMetadata({
433
- token: probeToken,
434
- apiUrl,
435
- fetchFn: input.fetchFn,
436
- });
437
- }
438
- catch (error) {
439
- if (error instanceof OpenApiError && error.status === 401) {
440
- throw new Error(`Could not read token metadata from ${apiUrl} (unauthorized). Run \`kody login\` or pass a valid --token / ${apiTokenEnvVar}.`);
441
- }
442
- throw error;
443
- }
444
- // Any live token's /tokens/current shape proves the origin supports org_binding.
445
- assertUserOwnedTokensLive(probeMetadata);
446
- }
447
- let storedMetadata = null;
448
- if (storedExisting) {
449
- if (probeMetadata && storedExisting.token === probeToken) {
450
- storedMetadata = probeMetadata;
451
- }
452
- else {
453
- try {
454
- storedMetadata = await fetchTokenCurrentMetadata({
455
- token: storedExisting.token,
456
- apiUrl,
457
- fetchFn: input.fetchFn,
458
- });
459
- }
460
- catch {
461
- storedMetadata = null;
462
- }
463
- }
464
- }
465
- const decision = decideSetupGitToken({
466
- stored: storedExisting,
467
- metadata: storedMetadata,
468
- scopesOverride: input.scopesOverride,
469
- lifetime: input.lifetime,
470
- });
471
- let stored;
472
- let minted = false;
473
- let backendKind;
474
- let backendPath;
475
- let finalMetadata;
476
- if (decision.action === 'reuse') {
477
- stored = decision.stored;
478
- backendKind = 'existing';
479
- finalMetadata = decision.metadata;
480
- }
481
- else {
482
- const result = await authBootstrapWithScopes({
483
- scopes: decision.scopes,
484
- lifetime: decision.lifetime,
485
- mint: input.mint,
486
- apiUrl,
487
- fetchFn: input.fetchFn,
488
- backend: input.backend,
489
- resolution: input.resolution,
490
- });
491
- stored = result.stored;
492
- minted = true;
493
- backendKind = result.backendKind;
494
- backendPath = result.backendPath;
495
- // Confirm the redeemed token is user-owned (new bootstrap default).
496
- const after = await fetchTokenCurrentMetadata({
497
- token: stored.token,
498
- apiUrl,
499
- fetchFn: input.fetchFn,
500
- });
501
- assertUserOwnedTokensLive(after);
502
- if (after.orgBinding !== 'user') {
503
- throw new Error(`Minted token ${stored.tokenId} has org_binding=${JSON.stringify(after.orgBinding)}; expected "user". Refusing to install the git helper.`);
504
- }
505
- if (!scopesIncludeRequired(after.scopes)) {
506
- throw new Error(`Minted token ${stored.tokenId} is missing package:read and/or package:write. Pass --scopes that include both.`);
507
- }
508
- finalMetadata = after;
509
- }
510
- const helperCommand = input.helperCommand ?? gitCredentialHelperCommand();
511
- installGitCredentialConfig({
512
- host,
513
- helperCommand,
514
- global: input.global,
515
- runGit: input.runGit,
516
- });
517
- return {
518
- host,
519
- helperCommand,
520
- tokenId: stored.tokenId,
521
- scopes: finalMetadata.scopes,
522
- orgBinding: 'user',
523
- minted,
524
- backendKind,
525
- ...(backendPath ? { backendPath } : {}),
526
- expiresAt: finalMetadata.expiresAt,
527
- };
528
- }
529
- /** Git config scopes `setup-git` may write (never `--system`). */
530
- export const setupGitConfigScopes = ['--global', '--local'];
531
- /**
532
- * True when a URL-scoped helper value was installed by Kody setup-git /
533
- * pin refresh (exact npx pin, major-only `@1`, ephemeral `_npx`, or a
534
- * `kody git-credential` invocation).
535
- */
536
- export function isKodyGitCredentialHelperValue(value) {
537
- const v = value.trim();
538
- if (!v)
539
- return false;
540
- if (v.includes('@kodycodes/cli'))
541
- return true;
542
- if (isEphemeralNpxEntryPath(v))
543
- return true;
544
- if (/\bgit-credential\b/.test(v) && /(^|[\/\s!])kody(\s|$)/.test(v))
545
- return true;
546
- if (/\bgit-credential\b/.test(v) && /kody/i.test(v))
547
- return true;
548
- return false;
549
- }
550
- /**
551
- * Inverse of {@link authSetupGit}: remove URL-scoped Kody credential helper
552
- * entries for the MCP host (global + local), revoke the stored API token
553
- * server-side, and delete it from the keychain/file store. Leaves `kody login`
554
- * OAuth sessions alone. Idempotent when nothing is configured.
555
- */
556
- export async function authRemoveGit(input) {
557
- const apiUrl = input.apiUrl || defaultApiUrl;
558
- const mcpUrl = input.mcpUrl || defaultMcpUrl;
559
- const host = gitCredentialHostFromMcpUrl(mcpUrl);
560
- const runGet = input.runGitGet ?? defaultGitConfigGetRunner;
561
- const runGit = input.runGit ?? defaultGitConfigRunner;
562
- const helperKey = `credential.https://${host}.helper`;
563
- const pathKey = `credential.https://${host}.useHttpPath`;
564
- const removedHelpers = [];
565
- const removedPathKeys = [];
566
- for (const scope of setupGitConfigScopes) {
567
- // URL-scoped keys for this host are owned by setup-git (exact pin,
568
- // major-only @1, ephemeral _npx, global kody, …). Clear them all.
569
- const helpers = runGet(['config', scope, '--get-all', helperKey]);
570
- if (helpers.status === 0 && helpers.stdout.trim()) {
571
- const values = helpers.stdout
572
- .split(/\r?\n/)
573
- .map((line) => line.trim())
574
- .filter(Boolean);
575
- const unset = runGit(['config', scope, '--unset-all', helperKey]);
576
- if (unset.status === 0) {
577
- for (const value of values) {
578
- removedHelpers.push({ scope, key: helperKey, value });
579
- }
580
- }
581
- }
582
- const pathGot = runGet(['config', scope, '--get-all', pathKey]);
583
- if (pathGot.status === 0 && pathGot.stdout.trim()) {
584
- const unset = runGit(['config', scope, '--unset-all', pathKey]);
585
- if (unset.status === 0) {
586
- removedPathKeys.push({
587
- scope,
588
- key: pathKey,
589
- value: pathGot.stdout.trim().split(/\r?\n/)[0],
590
- });
591
- }
592
- }
593
- }
594
- const stored = loadStoredApiToken(apiUrl, input.backend, input.resolution);
595
- let tokenRevoked = 'skipped';
596
- let tokenRevokeError;
597
- let tokenId = stored?.tokenId ?? null;
598
- if (stored?.token) {
599
- try {
600
- await openApiRequest({
601
- token: stored.token,
602
- apiUrl,
603
- method: 'DELETE',
604
- path: 'v1/tokens/current',
605
- fetchFn: input.fetchFn,
606
- });
607
- tokenRevoked = 'yes';
608
- }
609
- catch (error) {
610
- if (error instanceof OpenApiError && (error.status === 401 || error.status === 404)) {
611
- tokenRevoked = 'already';
612
- }
613
- else {
614
- tokenRevoked = 'failed';
615
- tokenRevokeError =
616
- error instanceof Error ? error.message : String(error);
617
- }
618
- }
619
- }
620
- const deleted = deleteStoredApiToken(apiUrl, input.backend, input.resolution);
621
- return {
622
- host,
623
- removedHelpers,
624
- removedPathKeys,
625
- tokenId,
626
- tokenRevoked,
627
- ...(tokenRevokeError ? { tokenRevokeError } : {}),
628
- tokenDeletedLocally: deleted.deleted,
629
- };
630
- }
631
- /** Human-readable lines for `kody auth remove-git` (always prints something). */
632
- export function formatAuthRemoveGitReport(result) {
633
- const lines = [];
634
- const removedAnything = result.removedHelpers.length > 0 ||
635
- result.removedPathKeys.length > 0 ||
636
- result.tokenDeletedLocally ||
637
- result.tokenRevoked === 'yes' ||
638
- result.tokenRevoked === 'already';
639
- if (!removedAnything) {
640
- return [
641
- `No Kody Git HTTPS credential helper or stored API token found for https://${result.host}/.`,
642
- 'Nothing to remove. (kody login sessions were not touched.)',
643
- '',
644
- ].join('\n');
645
- }
646
- lines.push(`Removed Kody Git HTTPS setup for https://${result.host}/`);
647
- for (const entry of result.removedHelpers) {
648
- lines.push(` ${entry.scope} ${entry.key}: ${entry.value}`);
649
- }
650
- for (const entry of result.removedPathKeys) {
651
- lines.push(` ${entry.scope} ${entry.key}${entry.value ? `: ${entry.value}` : ''}`);
652
- }
653
- if (result.tokenRevoked === 'yes') {
654
- lines.push(`Revoked API token${result.tokenId ? ` ${result.tokenId}` : ''} on the server (token:delete).`);
655
- }
656
- else if (result.tokenRevoked === 'already') {
657
- lines.push(`API token${result.tokenId ? ` ${result.tokenId}` : ''} already revoked or expired on the server.`);
658
- }
659
- else if (result.tokenRevoked === 'failed') {
660
- lines.push(`Could not revoke API token on the server${result.tokenRevokeError ? `: ${result.tokenRevokeError}` : '.'}`);
661
- }
662
- else if (result.tokenRevoked === 'skipped') {
663
- lines.push('No stored API token to revoke.');
664
- }
665
- if (result.tokenDeletedLocally) {
666
- lines.push('Deleted stored API token from the OS keychain (and file fallback).');
667
- }
668
- else if (result.tokenRevoked !== 'skipped') {
669
- lines.push('Stored API token was already absent from the local store.');
670
- }
671
- lines.push('Left kody login sessions alone.');
672
- lines.push('');
673
- return lines.join('\n');
674
- }
675
- export { cliTokenLifetimeAliases };
676
- //# sourceMappingURL=setup-git.js.map