@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.
- package/dist/auth-4FW6GCLG.js +26 -0
- package/dist/auth-4FW6GCLG.js.map +6 -0
- package/dist/bin.js +27 -3
- package/dist/bin.js.map +6 -1
- package/dist/chunk-46IJPEID.js +30 -0
- package/dist/chunk-46IJPEID.js.map +6 -0
- package/dist/chunk-4D6ORNXY.js +24404 -0
- package/dist/chunk-4D6ORNXY.js.map +6 -0
- package/dist/chunk-64IM6G4Z.js +341 -0
- package/dist/chunk-64IM6G4Z.js.map +6 -0
- package/dist/{package-local-runtime-source.js → chunk-64XN367G.js} +373 -52
- package/dist/chunk-64XN367G.js.map +6 -0
- package/dist/chunk-6XQP5SWX.js +26 -0
- package/dist/chunk-6XQP5SWX.js.map +6 -0
- package/dist/chunk-75RZUXQL.js +62 -0
- package/dist/chunk-75RZUXQL.js.map +6 -0
- package/dist/chunk-BISUL7CE.js +106 -0
- package/dist/chunk-BISUL7CE.js.map +6 -0
- package/dist/chunk-BPGY4IE7.js +57 -0
- package/dist/chunk-BPGY4IE7.js.map +6 -0
- package/dist/chunk-CASGRYOF.js +21 -0
- package/dist/chunk-CASGRYOF.js.map +6 -0
- package/dist/chunk-CWWHR4FH.js +19 -0
- package/dist/chunk-CWWHR4FH.js.map +6 -0
- package/dist/chunk-D55XPY3T.js +1382 -0
- package/dist/chunk-D55XPY3T.js.map +6 -0
- package/dist/chunk-EOCV74B2.js +948 -0
- package/dist/chunk-EOCV74B2.js.map +6 -0
- package/dist/chunk-FBVNFWR6.js +437 -0
- package/dist/chunk-FBVNFWR6.js.map +6 -0
- package/dist/chunk-G4YN6XP5.js +14 -0
- package/dist/chunk-G4YN6XP5.js.map +6 -0
- package/dist/chunk-G6LJWROP.js +18 -0
- package/dist/chunk-G6LJWROP.js.map +6 -0
- package/dist/chunk-IHP6PV6X.js +49 -0
- package/dist/chunk-IHP6PV6X.js.map +6 -0
- package/dist/chunk-JWEFKKAD.js +24 -0
- package/dist/chunk-JWEFKKAD.js.map +6 -0
- package/dist/chunk-LWNB26KO.js +147 -0
- package/dist/chunk-LWNB26KO.js.map +6 -0
- package/dist/chunk-OVGXPRSY.js +20 -0
- package/dist/chunk-OVGXPRSY.js.map +6 -0
- package/dist/chunk-PDWCKWQF.js +453 -0
- package/dist/chunk-PDWCKWQF.js.map +6 -0
- package/dist/chunk-QHBCP4OB.js +44 -0
- package/dist/chunk-QHBCP4OB.js.map +6 -0
- package/dist/chunk-R4IUV5P5.js +664 -0
- package/dist/chunk-R4IUV5P5.js.map +6 -0
- package/dist/chunk-RM34N3KI.js +525 -0
- package/dist/chunk-RM34N3KI.js.map +6 -0
- package/dist/chunk-RTWUNV76.js +309 -0
- package/dist/chunk-RTWUNV76.js.map +6 -0
- package/dist/chunk-SMURF26I.js +23 -0
- package/dist/chunk-SMURF26I.js.map +6 -0
- package/dist/chunk-SXHULGL4.js +426 -0
- package/dist/chunk-SXHULGL4.js.map +6 -0
- package/dist/chunk-TIL35OWA.js +1959 -0
- package/dist/chunk-TIL35OWA.js.map +6 -0
- package/dist/chunk-VQS5YSCI.js +54 -0
- package/dist/chunk-VQS5YSCI.js.map +6 -0
- package/dist/chunk-XDCOWU5R.js +696 -0
- package/dist/chunk-XDCOWU5R.js.map +6 -0
- package/dist/chunk-XOPPGRUP.js +605 -0
- package/dist/chunk-XOPPGRUP.js.map +6 -0
- package/dist/cli.js +74 -1500
- package/dist/cli.js.map +6 -1
- package/dist/dev-command-3LX234N6.js +4900 -0
- package/dist/dev-command-3LX234N6.js.map +6 -0
- package/dist/git-credential-FUE3JE3T.js +163 -0
- package/dist/git-credential-FUE3JE3T.js.map +6 -0
- package/dist/install-ZML2TCDG.js +10694 -0
- package/dist/install-ZML2TCDG.js.map +6 -0
- package/dist/local-execute-SZV6XN4T.js +368 -0
- package/dist/local-execute-SZV6XN4T.js.map +6 -0
- package/dist/local-package-run-2TMCAZZ2.js +23 -0
- package/dist/local-package-run-2TMCAZZ2.js.map +6 -0
- package/dist/mcp-G2AWTIXR.js +21 -0
- package/dist/mcp-G2AWTIXR.js.map +6 -0
- package/dist/mock-dep-resolve-TVABDNR7.js +52 -0
- package/dist/mock-dep-resolve-TVABDNR7.js.map +6 -0
- package/dist/mock-fetch-gateway-B5TFGGQS.js +34 -0
- package/dist/mock-fetch-gateway-B5TFGGQS.js.map +6 -0
- package/dist/mock-local-deps-5SZT3PWT.js +197 -0
- package/dist/mock-local-deps-5SZT3PWT.js.map +6 -0
- package/dist/mock-server-SV2IKC4I.js +21 -0
- package/dist/mock-server-SV2IKC4I.js.map +6 -0
- package/dist/open-api-client-DVVMLY7P.js +42 -0
- package/dist/open-api-client-DVVMLY7P.js.map +6 -0
- package/dist/org-X7B5BI4R.js +132 -0
- package/dist/org-X7B5BI4R.js.map +6 -0
- package/dist/package-manifest-QH2RU64C.js +14 -0
- package/dist/package-manifest-QH2RU64C.js.map +6 -0
- package/dist/remote-execute-QMQDVHOY.js +110 -0
- package/dist/remote-execute-QMQDVHOY.js.map +6 -0
- package/dist/setup-git-5KCUBYPB.js +88 -0
- package/dist/setup-git-5KCUBYPB.js.map +6 -0
- package/dist/skill-ENPATRIW.js +43 -0
- package/dist/skill-ENPATRIW.js.map +6 -0
- package/dist/store-WTMRH527.js +48 -0
- package/dist/store-WTMRH527.js.map +6 -0
- package/dist/structured-error-C65GQ53Z.js +13 -0
- package/dist/structured-error-C65GQ53Z.js.map +6 -0
- package/dist/target-3QHY7JT4.js +45 -0
- package/dist/target-3QHY7JT4.js.map +6 -0
- package/dist/webapi-NTVP4BO3.js +2482 -0
- package/dist/webapi-NTVP4BO3.js.map +6 -0
- package/package.json +8 -8
- package/dist/add-mcp-install.js +0 -59
- package/dist/add-mcp-install.js.map +0 -1
- package/dist/api-token-store.js +0 -120
- package/dist/api-token-store.js.map +0 -1
- package/dist/api-token.js +0 -238
- package/dist/api-token.js.map +0 -1
- package/dist/auth-bootstrap.js +0 -373
- package/dist/auth-bootstrap.js.map +0 -1
- package/dist/auth.js +0 -386
- package/dist/auth.js.map +0 -1
- package/dist/capability-proxy.js +0 -527
- package/dist/capability-proxy.js.map +0 -1
- package/dist/credential-call-map.js +0 -155
- package/dist/credential-call-map.js.map +0 -1
- package/dist/credential-client-runtime-source.js +0 -9
- package/dist/credential-client-runtime-source.js.map +0 -1
- package/dist/credentialed-fetch-scan.js +0 -98
- package/dist/credentialed-fetch-scan.js.map +0 -1
- package/dist/defaults.js +0 -34
- package/dist/defaults.js.map +0 -1
- package/dist/detect-running-hosts.js +0 -13
- package/dist/detect-running-hosts.js.map +0 -1
- package/dist/dev/dev-assets.js +0 -202
- package/dist/dev/dev-assets.js.map +0 -1
- package/dist/dev/dev-bundler.js +0 -65
- package/dist/dev/dev-bundler.js.map +0 -1
- package/dist/dev/dev-events.js +0 -94
- package/dist/dev/dev-events.js.map +0 -1
- package/dist/dev/dev-port.js +0 -80
- package/dist/dev/dev-port.js.map +0 -1
- package/dist/dev/dev-protocol.js +0 -14
- package/dist/dev/dev-protocol.js.map +0 -1
- package/dist/dev/dev-registry.js +0 -95
- package/dist/dev/dev-registry.js.map +0 -1
- package/dist/dev/dev-watcher.js +0 -162
- package/dist/dev/dev-watcher.js.map +0 -1
- package/dist/dev/error-page.js +0 -64
- package/dist/dev/error-page.js.map +0 -1
- package/dist/dev/live-reload.js +0 -151
- package/dist/dev/live-reload.js.map +0 -1
- package/dist/dev/prebuild.js +0 -102
- package/dist/dev/prebuild.js.map +0 -1
- package/dist/dev/process-reaper.js +0 -151
- package/dist/dev/process-reaper.js.map +0 -1
- package/dist/dev/stack-trace.js +0 -56
- package/dist/dev/stack-trace.js.map +0 -1
- package/dist/dev/workerd-process.js +0 -118
- package/dist/dev/workerd-process.js.map +0 -1
- package/dist/dev-command.js +0 -676
- package/dist/dev-command.js.map +0 -1
- package/dist/discover-login-identity.js +0 -77
- package/dist/discover-login-identity.js.map +0 -1
- package/dist/discover-org.js +0 -62
- package/dist/discover-org.js.map +0 -1
- package/dist/git-credential.js +0 -147
- package/dist/git-credential.js.map +0 -1
- package/dist/help.js +0 -333
- package/dist/help.js.map +0 -1
- package/dist/host-catalog.js +0 -427
- package/dist/host-catalog.js.map +0 -1
- package/dist/host-config.js +0 -80
- package/dist/host-config.js.map +0 -1
- package/dist/http-error-body.js +0 -35
- package/dist/http-error-body.js.map +0 -1
- package/dist/install-hosts.js +0 -328
- package/dist/install-hosts.js.map +0 -1
- package/dist/install.js +0 -120
- package/dist/install.js.map +0 -1
- package/dist/invoke-passthrough.js +0 -60
- package/dist/invoke-passthrough.js.map +0 -1
- package/dist/local-bundle.js +0 -200
- package/dist/local-bundle.js.map +0 -1
- package/dist/local-execute-auth.js +0 -53
- package/dist/local-execute-auth.js.map +0 -1
- package/dist/local-execute.js +0 -338
- package/dist/local-execute.js.map +0 -1
- package/dist/local-gateway-fetch-forward.js +0 -135
- package/dist/local-gateway-fetch-forward.js.map +0 -1
- package/dist/local-host-runtime-surface.js +0 -75
- package/dist/local-host-runtime-surface.js.map +0 -1
- package/dist/local-package-graph.js +0 -405
- package/dist/local-package-graph.js.map +0 -1
- package/dist/local-package-run.js +0 -307
- package/dist/local-package-run.js.map +0 -1
- package/dist/local-runtime-bridge.js +0 -132
- package/dist/local-runtime-bridge.js.map +0 -1
- package/dist/local-runtime-source.js +0 -541
- package/dist/local-runtime-source.js.map +0 -1
- package/dist/login-callback-assets.js +0 -10
- package/dist/login-callback-assets.js.map +0 -1
- package/dist/login-callback-page.js +0 -362
- package/dist/login-callback-page.js.map +0 -1
- package/dist/mcp.js +0 -134
- package/dist/mcp.js.map +0 -1
- package/dist/mock/ensure-msw.js +0 -215
- package/dist/mock/ensure-msw.js.map +0 -1
- package/dist/mock/install-mock-fetch-shim.js +0 -36
- package/dist/mock/install-mock-fetch-shim.js.map +0 -1
- package/dist/mock/load-package-mocks.js +0 -136
- package/dist/mock/load-package-mocks.js.map +0 -1
- package/dist/mock/mock-fetch-gateway.js +0 -343
- package/dist/mock/mock-fetch-gateway.js.map +0 -1
- package/dist/mock/mock-gateway-fetch-shim.js +0 -104
- package/dist/mock/mock-gateway-fetch-shim.js.map +0 -1
- package/dist/mock/mock-server.js +0 -499
- package/dist/mock/mock-server.js.map +0 -1
- package/dist/mock/mock-storage.js +0 -186
- package/dist/mock/mock-storage.js.map +0 -1
- package/dist/mock/mock-supported.js +0 -63
- package/dist/mock/mock-supported.js.map +0 -1
- package/dist/mock-dep-resolve.js +0 -47
- package/dist/mock-dep-resolve.js.map +0 -1
- package/dist/mock-local-deps.js +0 -207
- package/dist/mock-local-deps.js.map +0 -1
- package/dist/network-error.js +0 -11
- package/dist/network-error.js.map +0 -1
- package/dist/node-engine.js +0 -21
- package/dist/node-engine.js.map +0 -1
- package/dist/oauth-provider.js +0 -107
- package/dist/oauth-provider.js.map +0 -1
- package/dist/onboarding-prompt.js +0 -15
- package/dist/onboarding-prompt.js.map +0 -1
- package/dist/open-api-client.js +0 -432
- package/dist/open-api-client.js.map +0 -1
- package/dist/open-url.js +0 -21
- package/dist/open-url.js.map +0 -1
- package/dist/org-resolve.js +0 -16
- package/dist/org-resolve.js.map +0 -1
- package/dist/org-slug.js +0 -11
- package/dist/org-slug.js.map +0 -1
- package/dist/org.js +0 -100
- package/dist/org.js.map +0 -1
- package/dist/package-app-dev.js +0 -922
- package/dist/package-app-dev.js.map +0 -1
- package/dist/package-collaborators.js +0 -179
- package/dist/package-collaborators.js.map +0 -1
- package/dist/package-info.js +0 -19
- package/dist/package-info.js.map +0 -1
- package/dist/package-local-runtime-source.js.map +0 -1
- package/dist/package-manifest.js +0 -364
- package/dist/package-manifest.js.map +0 -1
- package/dist/process-info.js +0 -14
- package/dist/process-info.js.map +0 -1
- package/dist/redact.js +0 -16
- package/dist/redact.js.map +0 -1
- package/dist/remote-execute.js +0 -108
- package/dist/remote-execute.js.map +0 -1
- package/dist/setup-git.js +0 -676
- package/dist/setup-git.js.map +0 -1
- package/dist/skill.js +0 -35
- package/dist/skill.js.map +0 -1
- package/dist/store.js +0 -597
- package/dist/store.js.map +0 -1
- package/dist/structured-error.js +0 -57
- package/dist/structured-error.js.map +0 -1
- package/dist/target.js +0 -52
- package/dist/target.js.map +0 -1
- package/dist/tool-result.js +0 -19
- package/dist/tool-result.js.map +0 -1
- package/dist/which.js +0 -22
- package/dist/which.js.map +0 -1
- package/dist/workerd-binary.js +0 -98
- package/dist/workerd-binary.js.map +0 -1
|
@@ -0,0 +1,1959 @@
|
|
|
1
|
+
import { createRequire as __createRequire } from 'node:module'; const require = __createRequire(import.meta.url);
|
|
2
|
+
import {
|
|
3
|
+
assertLocalExecuteNodeEngine
|
|
4
|
+
} from "./chunk-SMURF26I.js";
|
|
5
|
+
import {
|
|
6
|
+
isPublishedPackageInvokeSpecifier,
|
|
7
|
+
resolveExecuteInvokeCode
|
|
8
|
+
} from "./chunk-75RZUXQL.js";
|
|
9
|
+
import {
|
|
10
|
+
formatToolResult
|
|
11
|
+
} from "./chunk-46IJPEID.js";
|
|
12
|
+
import {
|
|
13
|
+
hostIds
|
|
14
|
+
} from "./chunk-PDWCKWQF.js";
|
|
15
|
+
import {
|
|
16
|
+
resolveOrgSlug
|
|
17
|
+
} from "./chunk-OVGXPRSY.js";
|
|
18
|
+
import {
|
|
19
|
+
resolveLocalExecuteBearer
|
|
20
|
+
} from "./chunk-VQS5YSCI.js";
|
|
21
|
+
import {
|
|
22
|
+
authBootstrap,
|
|
23
|
+
authBootstrapWithScopes,
|
|
24
|
+
bootstrapMintLifetimeFields,
|
|
25
|
+
cliCredentialBootstrapOperationId,
|
|
26
|
+
parseCliLifetimeSecondsFlag,
|
|
27
|
+
parseCliScopesFlag,
|
|
28
|
+
refreshGitCredentialHelperPinIfNeeded,
|
|
29
|
+
resolveCliTokenLifetime
|
|
30
|
+
} from "./chunk-EOCV74B2.js";
|
|
31
|
+
import {
|
|
32
|
+
parseCredentialFlags
|
|
33
|
+
} from "./chunk-R4IUV5P5.js";
|
|
34
|
+
import {
|
|
35
|
+
redactError
|
|
36
|
+
} from "./chunk-CASGRYOF.js";
|
|
37
|
+
import {
|
|
38
|
+
orgEnvVar,
|
|
39
|
+
orgSlugFromFlag
|
|
40
|
+
} from "./chunk-CWWHR4FH.js";
|
|
41
|
+
import {
|
|
42
|
+
readPackageVersion
|
|
43
|
+
} from "./chunk-G6LJWROP.js";
|
|
44
|
+
import {
|
|
45
|
+
cliBootstrapMintCall,
|
|
46
|
+
deleteStoredApiToken,
|
|
47
|
+
hasExplicitTokenFlag,
|
|
48
|
+
loadStoredApiToken,
|
|
49
|
+
requireApiToken,
|
|
50
|
+
resolveScopedApiToken
|
|
51
|
+
} from "./chunk-RTWUNV76.js";
|
|
52
|
+
import {
|
|
53
|
+
deleteCredentials,
|
|
54
|
+
listStoredOrgs,
|
|
55
|
+
loadCredentials
|
|
56
|
+
} from "./chunk-RM34N3KI.js";
|
|
57
|
+
import {
|
|
58
|
+
apiTokenEnvVar,
|
|
59
|
+
defaultApiUrl,
|
|
60
|
+
defaultMcpUrl,
|
|
61
|
+
modernMcpProtocolVersion,
|
|
62
|
+
onboardingUrl
|
|
63
|
+
} from "./chunk-IHP6PV6X.js";
|
|
64
|
+
|
|
65
|
+
// src/cli.ts
|
|
66
|
+
import { parseArgs } from "node:util";
|
|
67
|
+
import { readFile } from "node:fs/promises";
|
|
68
|
+
|
|
69
|
+
// src/help.ts
|
|
70
|
+
function formatOrgsHelpBlock(orgs, indent = " ") {
|
|
71
|
+
if (orgs.length === 0) {
|
|
72
|
+
return `${indent}Not logged in. Run \`kody login\`.
|
|
73
|
+
`;
|
|
74
|
+
}
|
|
75
|
+
const lines = [`${indent}Logged-in orgs:`];
|
|
76
|
+
for (const org of orgs) {
|
|
77
|
+
const mark = org.active ? "*" : " ";
|
|
78
|
+
const pending = org.pending ? " (slug pending \u2014 run any authenticated command)" : "";
|
|
79
|
+
lines.push(
|
|
80
|
+
`${indent} ${mark} ${org.slug}${org.active ? " (active)" : ""}${pending}`
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
return `${lines.join("\n")}
|
|
84
|
+
`;
|
|
85
|
+
}
|
|
86
|
+
function buildUsage(input = {}) {
|
|
87
|
+
const mcpUrl = input.mcpUrl ?? defaultMcpUrl;
|
|
88
|
+
let orgs = input.orgs;
|
|
89
|
+
if (!orgs) {
|
|
90
|
+
try {
|
|
91
|
+
orgs = listStoredOrgs(mcpUrl, input.backend, input.resolution);
|
|
92
|
+
} catch {
|
|
93
|
+
orgs = [];
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
const orgBlock = formatOrgsHelpBlock(orgs);
|
|
97
|
+
return `Kody CLI ${readPackageVersion()}
|
|
98
|
+
|
|
99
|
+
Install Kody as a remote MCP server in local agents, or use this CLI as a local client.
|
|
100
|
+
|
|
101
|
+
Usage:
|
|
102
|
+
kody login [--mcp-url <url>] [--org <slug>] [--no-browser]
|
|
103
|
+
kody logout [--org <slug>] [--mcp-url <url>] [--api-url <url>]
|
|
104
|
+
kody org list [--json] [--mcp-url <url>]
|
|
105
|
+
kody org use [<slug>] [--mcp-url <url>]
|
|
106
|
+
kody status [--mcp-url <url>] [--api-url <url>]
|
|
107
|
+
kody auth bootstrap (--code <kody_bc_\u2026> | --scopes <list>) (--lifetime short|long | --idle-ttl-seconds <n> --max-lifetime-seconds <n>)
|
|
108
|
+
[--token <token>] [--mcp-url <url>] [--api-url <url>]
|
|
109
|
+
kody auth setup-git [--lifetime long|short] [--scopes <list>] [--token <token>] [--mcp-url <url>] [--api-url <url>]
|
|
110
|
+
kody auth remove-git [--mcp-url <url>] [--api-url <url>]
|
|
111
|
+
kody git-credential <get|store|erase>
|
|
112
|
+
kody whoami [--org <slug>] [--target prod|mock] [--mcp-url <url>] [--token <token>] [--api-url <url>] [--json]
|
|
113
|
+
kody search [query] [--org <slug>] [--entity <ref>] [--domain <id>] [--limit <n>] [--target prod|mock] [--token <token>] [--api-url <url>] [--json]
|
|
114
|
+
kody api <operationId> [--org <slug>] [--params <json>] [--token <token>] [--api-url <url>] [--json]
|
|
115
|
+
kody package publish [<@owner/leaf|package_id>] [--org <slug>] [--params <json>] [--token <token>] [--api-url <url>]
|
|
116
|
+
kody package collaborators <package> [--org <slug>] [--json] [--token <token>] [--api-url <url>]
|
|
117
|
+
kody package grant <package> (--team <slug> | --user <username>) [--preset use|contribute|manage] [--org <slug>] [--json]
|
|
118
|
+
kody package revoke <package> (--team <slug> | --user <username> | --grant <grant_id>) [--org <slug>] [--json]
|
|
119
|
+
kody execute [--org <slug>] [--invoke <ref> | --code <esm> | --file <path>] [--params <json>] [--conversation-id <id>] [--json]
|
|
120
|
+
[--credential <key=name>]\u2026 [--target prod|mock] [--token <token>] [--api-url <url>] [--local] [--allow-private-network]
|
|
121
|
+
kody dev [serve] [--org <slug>] [--target prod|mock] [--reset-storage] [--port <n>] [--app-base-path <path>] [--allow-private-network] [--no-live-reload] [--json] [--ready-file <path>]
|
|
122
|
+
kody dev fetch <path> [--method <verb>] [--body <file>] [--target prod|mock] [--json] [--no-attach]
|
|
123
|
+
kody dev job <name> [--target prod|mock] [--dry-run] [--json]
|
|
124
|
+
kody dev webhook <name> --body <file.json> [--target prod|mock] [--dry-run] [--json]
|
|
125
|
+
kody dev emit <event> --body <event.json> [--target prod|mock] [--dry-run] [--json]
|
|
126
|
+
kody dev check [--target prod|mock] [--json]
|
|
127
|
+
kody install [--mcp-url <url>] [--clients <ids>] [--yes] [--project] [--json]
|
|
128
|
+
kody skill install [--project]
|
|
129
|
+
|
|
130
|
+
kody install configures running local MCP clients (Cursor, Claude Desktop,
|
|
131
|
+
VS Code, Goose, and others). For web-based clients (ChatGPT, Claude.ai, Grok),
|
|
132
|
+
see ${onboardingUrl(defaultMcpUrl)}
|
|
133
|
+
|
|
134
|
+
Orgs (local store, offline):
|
|
135
|
+
${orgBlock}
|
|
136
|
+
--org <slug>
|
|
137
|
+
For \`kody login\` / \`kody logout\`: only the flag counts
|
|
138
|
+
(${orgEnvVar} is ignored). Login binds the browser grant to
|
|
139
|
+
this organization (adds/replaces that org's stored login;
|
|
140
|
+
other orgs stay). Example: \`kody login --org acme\`
|
|
141
|
+
Omit and the server picker binds one org.
|
|
142
|
+
For org-scoped commands (whoami, search, api, execute, \u2026):
|
|
143
|
+
run as this org for one call. Precedence: flag, then
|
|
144
|
+
${orgEnvVar}, then the active org (\`kody org use\`).
|
|
145
|
+
|
|
146
|
+
kody org list
|
|
147
|
+
Show logged-in orgs and mark the active one. \`--json\` for agents.
|
|
148
|
+
|
|
149
|
+
kody org use [<slug>]
|
|
150
|
+
Switch the active org. With a slug (agents), switches directly.
|
|
151
|
+
With no slug on a TTY (humans), opens an interactive chooser.
|
|
152
|
+
Without a TTY, pass a slug.
|
|
153
|
+
|
|
154
|
+
kody logout
|
|
155
|
+
Without \`--org\`, removes the active org login only (or the
|
|
156
|
+
pending legacy session). With \`--org <slug>\`, removes just
|
|
157
|
+
that org. Other org logins stay. Also clears a stored
|
|
158
|
+
bootstrap/API token when present.
|
|
159
|
+
|
|
160
|
+
--clients Comma-separated ids: ${hostIds.join(", ")}
|
|
161
|
+
|
|
162
|
+
auth bootstrap
|
|
163
|
+
Redeem a one-shot \`kody_bc_\u2026\` from MCP \`cliCredentialBootstrap\`
|
|
164
|
+
(POST /v1/tokens/bootstrap/redeem, no Authorization header).
|
|
165
|
+
Lifetime is required: \`--lifetime short|long\` (\`short\` = 1h
|
|
166
|
+
idle / 24h max; \`long\` = 14d idle / 3mo max), or both
|
|
167
|
+
\`--idle-ttl-seconds\` and \`--max-lifetime-seconds\`.
|
|
168
|
+
Single-task agents should use \`--lifetime short\`.
|
|
169
|
+
Stores the resulting \`kody_at_\u2026\` for \`execute --local\`,
|
|
170
|
+
search, whoami, api, and token-auth cloud execute without
|
|
171
|
+
printing the token. Prefer this over tokenCreate for agents
|
|
172
|
+
already on MCP. Interactive humans can use \`kody login\`
|
|
173
|
+
instead. Do not call \`kody api cliCredentialBootstrapRedeem\`
|
|
174
|
+
\u2014 that would print the token.
|
|
175
|
+
|
|
176
|
+
--scopes <list>
|
|
177
|
+
Opt in to scopes beyond the cliCredentialBootstrap defaults
|
|
178
|
+
(comma- or space-separated, e.g.
|
|
179
|
+
\`--scopes org:execute,org:read,package:read,package:write\`).
|
|
180
|
+
The list replaces the defaults, so include every scope you
|
|
181
|
+
need. Instead of \`--code\`, the CLI mints the code itself by
|
|
182
|
+
passing \`scopes\` to cliCredentialBootstrap, then redeems and
|
|
183
|
+
stores it. It mints with \`--token\` if given, else the
|
|
184
|
+
\`kody login\` session (any scope your org role grants), else
|
|
185
|
+
${apiTokenEnvVar} / a stored token (only scopes that token
|
|
186
|
+
already holds). A bootstrap code's scopes are fixed when it is
|
|
187
|
+
minted, so \`--code\` with \`--scopes\` is an error. Defaults
|
|
188
|
+
stay least-privilege; \`insufficient_scope\` errors print the
|
|
189
|
+
exact \`--scopes\` command to run.
|
|
190
|
+
|
|
191
|
+
auth setup-git
|
|
192
|
+
Install a Git credential helper for HTTPS clones/fetches/pushes
|
|
193
|
+
at \`https://kody.codes/@owner/name.git\` (see guide:auth_setup_git).
|
|
194
|
+
Uses a \`kody login\` session (or \`--token\` / ${apiTokenEnvVar} /
|
|
195
|
+
stored bootstrap token) to mint a user-owned \`kody_at_\u2026\` with
|
|
196
|
+
at least \`package:read\` and \`package:write\` (default
|
|
197
|
+
\`--lifetime long\`; reuses a suitable stored token). That token
|
|
198
|
+
authorizes every repo you can access across all orgs \u2014 login
|
|
199
|
+
\`--org\` only scopes the MCP mint session, not git. User-wide:
|
|
200
|
+
one setup covers every org. Requires a server that advertises
|
|
201
|
+
\`org_binding\`. Configures a stable
|
|
202
|
+
\`credential.https://<host>.helper\` (global \`kody\` only when
|
|
203
|
+
its version supports \`git-credential\`, else
|
|
204
|
+
\`npx -y @kodycodes/cli@<exact>\` \u2014 never a major-only range or
|
|
205
|
+
ephemeral npx cache path) + \`useHttpPath\`. Re-run (or any
|
|
206
|
+
newer CLI command) rewrites stale helper pins. Undo with
|
|
207
|
+
\`kody auth remove-git\`. Does not change \`kody login\` /
|
|
208
|
+
existing auth flows.
|
|
209
|
+
|
|
210
|
+
auth remove-git
|
|
211
|
+
Inverse of \`auth setup-git\`: removes every
|
|
212
|
+
\`credential.https://<host>.*\` helper entry setup-git may have
|
|
213
|
+
written (global and local; including stale \`~/.npm/_npx\` and
|
|
214
|
+
major-only \`@1\` pins), revokes the stored API token on the
|
|
215
|
+
server (\`token:delete\` / DELETE /v1/tokens/current), and
|
|
216
|
+
deletes it from the OS keychain. Idempotent when nothing is
|
|
217
|
+
set up; prints what it removed. Leaves \`kody login\` sessions
|
|
218
|
+
alone.
|
|
219
|
+
|
|
220
|
+
git-credential
|
|
221
|
+
Git credential helper invoked by git after \`auth setup-git\`
|
|
222
|
+
(\`get\` returns username=x / password=kody_at_\u2026 for the Kody
|
|
223
|
+
host with no network while the stored token is still valid;
|
|
224
|
+
silently remints via \`kody login\` only when expired or near
|
|
225
|
+
expiry; \`store\`/\`erase\` are no-ops). Not meant for interactive
|
|
226
|
+
use.
|
|
227
|
+
|
|
228
|
+
api Call one Open API operation by operationId + flat --params
|
|
229
|
+
JSON (same shape as the MCP \`api\` tool). Uses scoped API
|
|
230
|
+
auth only (\`--token\` / ${apiTokenEnvVar} / stored bootstrap).
|
|
231
|
+
Prints JSON. Example: \`kody api usageGet --params '{}'\`.
|
|
232
|
+
Unknown operationIds error clearly; see
|
|
233
|
+
${defaultApiUrl}/openapi.json. tokenCreate / tokenRotate
|
|
234
|
+
responses include a one-time token value \u2014 prefer env storage
|
|
235
|
+
over pasting into chat.
|
|
236
|
+
|
|
237
|
+
package publish
|
|
238
|
+
Thin wrapper for Open API \`packagePublishExternalPush\` (same
|
|
239
|
+
auth as \`kody api\`). Optional positional is a \`package_id\`, or a
|
|
240
|
+
name (\`@owner/leaf\` or bare leaf) resolved to its package_id
|
|
241
|
+
via \`packageList\` in the current org. Extra fields
|
|
242
|
+
via \`--params\` JSON (e.g. \`allow_force\`). Prints JSON.
|
|
243
|
+
|
|
244
|
+
package collaborators | grant | revoke
|
|
245
|
+
Who can use one package, and add or remove teams and members of
|
|
246
|
+
the org (\`--org\`). \`<package>\` is \`@owner/leaf\`, the kody id,
|
|
247
|
+
or the package id. \`grant\` adds a team or org member or changes
|
|
248
|
+
their preset (default \`use\`) via \`packageCollaboratorSet\`;
|
|
249
|
+
people outside the org are refused. \`revoke\` removes one by
|
|
250
|
+
team, user, or grant id via \`packageCollaboratorRemove\`. Needs
|
|
251
|
+
Manage on the package and a token with
|
|
252
|
+
\`package:manage_access\` (\`auth bootstrap --scopes \u2026\`); same
|
|
253
|
+
auth as \`kody api\`. Prints a short summary, or the API JSON
|
|
254
|
+
with \`--json\`.
|
|
255
|
+
|
|
256
|
+
--token / ${apiTokenEnvVar}
|
|
257
|
+
Scoped API token (preferred via env). With no \`kody login\`
|
|
258
|
+
session, search / whoami / api / execute use the Open API and
|
|
259
|
+
CapabilityProxy \u2014 including cloud execute without --local.
|
|
260
|
+
Auth priority matches \`execute --local\`: \`--token\` /
|
|
261
|
+
${apiTokenEnvVar}; stored bootstrap/API token from
|
|
262
|
+
\`auth bootstrap\`; then \`kody login\` where applicable.
|
|
263
|
+
Prefer \`cliCredentialBootstrap\` then \`auth bootstrap\`
|
|
264
|
+
(\`--lifetime short|long\`). CI/headless: \`tokenCreate\` with
|
|
265
|
+
\`org:execute\` plus the capability scopes you need.
|
|
266
|
+
For \`execute --local\`, a valid \`kody login\` session can also
|
|
267
|
+
supply Bearer when no scoped token is available (no tokenCreate
|
|
268
|
+
exchange). User-owned tokens (\`org_binding: user\`) honor
|
|
269
|
+
\`--org\` / ${orgEnvVar} as \`?org=\` on API calls.
|
|
270
|
+
|
|
271
|
+
--local Run the execute module on this machine (workerd, Linux/macOS).
|
|
272
|
+
Requires Node.js 22 or newer. \`--file\` entries are bundled
|
|
273
|
+
(relative imports and npm packages; \`kody:*\` stays external)
|
|
274
|
+
before workerd loads them \u2014 same shape as hosted execute /
|
|
275
|
+
publish. Unresolvable imports fail with a clear bundle error.
|
|
276
|
+
\`--invoke kody:@scope/pkg/export\` (or \`@scope/pkg#export\`)
|
|
277
|
+
works with \`--local\` / \`--target mock\` \u2014 mints the same thin
|
|
278
|
+
passthrough as a \`--code\` import wrapper. From a package
|
|
279
|
+
directory, \`--invoke ./export\` runs a local package.json#exports
|
|
280
|
+
key. Auth: \`--token\` /
|
|
281
|
+
${apiTokenEnvVar}, else stored \`auth bootstrap\` token, else
|
|
282
|
+
paired \`kody login\` credentials. Static kody:@\u2026 imports are fetched via POST
|
|
283
|
+
/v1/local-execute/package-graph and embedded in local workerd
|
|
284
|
+
(CapabilityProxy only for per-call kody:runtime hops \u2014 never a
|
|
285
|
+
whole-module cloud kody.execute defer). Fails clearly when that
|
|
286
|
+
package-graph API is unavailable. Cloud token execute (no
|
|
287
|
+
--local) uses CapabilityProxy \u2192 kody.execute for every module.
|
|
288
|
+
|
|
289
|
+
--credential <key=name>
|
|
290
|
+
ADR 0068 call map: pick which credential each \`credential(key)\`
|
|
291
|
+
/ \`credentials(key)\` call gets. Repeatable.
|
|
292
|
+
\`--credential github=work\`, \`--credential x=org:work\`
|
|
293
|
+
(or \`personal:name\`), \`--credential github=\` for none on
|
|
294
|
+
purpose. With \`--local\`, sent as CapabilityProxy top-level
|
|
295
|
+
\`credentials\` (code never sets the map) after a
|
|
296
|
+
\`credentialClientCheck\` preflight. With a \`kody login\` MCP
|
|
297
|
+
session (no token), passed as MCP execute \`credentials\`.
|
|
298
|
+
Token-auth cloud execute (CapabilityProxy \u2192 kody.execute)
|
|
299
|
+
rejects the flag \u2014 use \`--local\` or MCP.
|
|
300
|
+
|
|
301
|
+
--allow-private-network
|
|
302
|
+
Allow execute --local / \`kody dev\` code to fetch private and
|
|
303
|
+
local network addresses. Default is public-only.
|
|
304
|
+
|
|
305
|
+
--target prod|mock
|
|
306
|
+
Where server-side calls go (storage, credentials, kody:*,
|
|
307
|
+
execute, invoke, search). Same meaning on \`dev\`, \`execute\`,
|
|
308
|
+
and \`search\`. Defaults: \`mock\` for \`kody dev\`; \`prod\` for
|
|
309
|
+
execute/search (unchanged). \`--target mock\` starts the
|
|
310
|
+
built-in CLI mock (no kody-celld); scratch storage; fake or
|
|
311
|
+
local credentials so unpublished packages never touch real
|
|
312
|
+
secrets. Unimplemented mock routes refuse with
|
|
313
|
+
\`not_implemented_in_mock\`.
|
|
314
|
+
|
|
315
|
+
--reset-storage
|
|
316
|
+
With \`--target mock\`, wipe the mock session's scratch storage
|
|
317
|
+
before the command.
|
|
318
|
+
|
|
319
|
+
--dry-run With \`kody dev job|webhook|emit\`, print the module path and
|
|
320
|
+
params that would run without invoking (safe against prod side
|
|
321
|
+
effects). Does not apply to serve/fetch/check.
|
|
322
|
+
|
|
323
|
+
--passthrough <host,\u2026>
|
|
324
|
+
With \`--target mock\` and a package \`.kody/mocks.ts\`, allow
|
|
325
|
+
listed hosts to use the real network (credentials stay fake \u2014
|
|
326
|
+
never carries real secrets). Unmatched hosts fail with
|
|
327
|
+
\`unmocked_request\` plus a paste-ready MSW handler stub.
|
|
328
|
+
Ignored on \`--target prod\`. On mock, outbound fetch always
|
|
329
|
+
goes through the Node gateway: with \`.kody/mocks.ts\`, unmatched
|
|
330
|
+
hosts (and all \`createAuthenticatedFetch\` / credentialed hops
|
|
331
|
+
without a handler) fail closed; without the file, public hosts
|
|
332
|
+
passthrough and private hosts need \`--allow-private-network\`.
|
|
333
|
+
|
|
334
|
+
kody dev Local testing for unpublished packages. Serves \`kody.app.entry\`
|
|
335
|
+
on localhost via workerd with hot reload (mount-stripped path;
|
|
336
|
+
packageContext.hostedUrl / appBasePath point at localhost).
|
|
337
|
+
Rebuilds swap to a new workerd only once it listens (requests
|
|
338
|
+
wait; no 503 or stale bundle). Build errors (file:line:col +
|
|
339
|
+
code frame) and uncaught handler errors (stack mapped to your
|
|
340
|
+
.ts sources) are served as dev-only 500 pages until fixed. App
|
|
341
|
+
console.* streams to the terminal tagged by request. HTML pages
|
|
342
|
+
live-reload after each rebuild and show an error overlay
|
|
343
|
+
(SSE at /__kody/dev/events; \`--no-live-reload\` disables).
|
|
344
|
+
Stable default port per package (4100-4999, next free port
|
|
345
|
+
if taken); \`--port <n>\` is exact (\`--port 0\` = any).
|
|
346
|
+
Serves \`kody.app.client\` at /_assets/client.<hash>.js
|
|
347
|
+
(packageContext.clientModuleUrl), \`kody.app.assets\` under
|
|
348
|
+
/_assets/, and /_assets/__version.json. \`kody.dev.prebuild\`
|
|
349
|
+
(shell command, run before every build) regenerates assets;
|
|
350
|
+
\`kody.dev.ignore\` lists watcher path prefixes to skip.
|
|
351
|
+
Agents: \`--json\` streams NDJSON events (ready, rebuild_start,
|
|
352
|
+
rebuild_ok, build_error, runtime_error, log); GET
|
|
353
|
+
/__kody/dev/status returns build id + last error;
|
|
354
|
+
\`--ready-file <path>\` writes { url, port, basePath, pid } once
|
|
355
|
+
ready. \`kody dev fetch\` attaches to a running \`kody dev\` for
|
|
356
|
+
the same package and target (\`--no-attach\` boots a one-shot
|
|
357
|
+
server).
|
|
358
|
+
Bundles with the same esbuild path as publish (\`local-bundle\`).
|
|
359
|
+
Four surfaces: exports (\`execute --invoke ./export\` or
|
|
360
|
+
\`--file\` against the local package), webhooks
|
|
361
|
+
(\`kody dev webhook\`), schedules (\`kody dev job\` \u2014 runs once,
|
|
362
|
+
never schedules locally), subscriptions
|
|
363
|
+
(\`kody dev emit <event> --body event.json\`). \`kody dev check\`
|
|
364
|
+
bundles + light publish validations without running; when the
|
|
365
|
+
package uses credentialed fetch and \`.kody/mocks.ts\` is
|
|
366
|
+
missing, check soft-suggests adding that file. On
|
|
367
|
+
\`--target mock\`, \`kody:@\` deps resolve from this package's
|
|
368
|
+
exports, \`.kody/deps.json\` / \`package.json#kody.localDeps\`
|
|
369
|
+
path maps, then published package-graph when a login/API token
|
|
370
|
+
is available (storage/credentials stay on the mock; local-only
|
|
371
|
+
deps need no login). Optional \`.kody/mocks.ts\` exports MSW
|
|
372
|
+
\`handlers\` for outbound fetch mocking (Node gateway; not
|
|
373
|
+
published with the package) \u2014 \`createAuthenticatedFetch\`,
|
|
374
|
+
\`credential().fetch\`, \`gatewayFetch\`, and
|
|
375
|
+
\`gatewayFetchStream\` all match against them. Unmocked
|
|
376
|
+
requests fail closed with a ready-to-paste MSW handler stub
|
|
377
|
+
pointing at \`.kody/mocks.ts\`. Share previews are out of scope.
|
|
378
|
+
|
|
379
|
+
Environment:
|
|
380
|
+
KODY_MCP_URL Override the default MCP URL (${defaultMcpUrl})
|
|
381
|
+
${orgEnvVar} Default org slug for org-scoped commands (overridden by --org)
|
|
382
|
+
${apiTokenEnvVar} Scoped API token for token-auth search / whoami / api / execute
|
|
383
|
+
KODY_API_URL Override the Kody API URL (${defaultApiUrl})
|
|
384
|
+
KODY_TARGET Default \`prod\`|\`mock\` (overridden by --target)
|
|
385
|
+
KODY_MOCK_SESSION_ID Scratch storage key for --target mock (default: default)
|
|
386
|
+
KODY_CACHE_DIR Where execute --local caches workerd (default: user cache dir)
|
|
387
|
+
KODY_WORKERD_PATH Use this workerd binary instead of the pinned download
|
|
388
|
+
`;
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
// src/package-collaborators.ts
|
|
392
|
+
var packageCollaboratorPresets = ["use", "contribute", "manage"];
|
|
393
|
+
var packageCollaboratorActions = [
|
|
394
|
+
"collaborators",
|
|
395
|
+
"grant",
|
|
396
|
+
"revoke"
|
|
397
|
+
];
|
|
398
|
+
function isPackageCollaboratorAction(value) {
|
|
399
|
+
return packageCollaboratorActions.includes(value);
|
|
400
|
+
}
|
|
401
|
+
var packageCollaboratorUsage = [
|
|
402
|
+
"Usage: kody package collaborators <@owner/leaf|kody_id|package_id> [--org <slug>] [--json]",
|
|
403
|
+
" kody package grant <package> (--team <slug> | --user <username>) [--preset use|contribute|manage] [--org <slug>] [--json]",
|
|
404
|
+
" kody package revoke <package> (--team <slug> | --user <username> | --grant <grant_id>) [--org <slug>] [--json]"
|
|
405
|
+
].join("\n");
|
|
406
|
+
function readFlag(value, name) {
|
|
407
|
+
if (value === void 0) return void 0;
|
|
408
|
+
if (typeof value !== "string" || value.trim() === "") {
|
|
409
|
+
throw new Error(`--${name} needs a value.
|
|
410
|
+
${packageCollaboratorUsage}`);
|
|
411
|
+
}
|
|
412
|
+
return value.trim();
|
|
413
|
+
}
|
|
414
|
+
function readSubject(values, allowGrant) {
|
|
415
|
+
const team = readFlag(values.team, "team");
|
|
416
|
+
const user = readFlag(values.user, "user");
|
|
417
|
+
const grant = allowGrant ? readFlag(values.grant, "grant") : void 0;
|
|
418
|
+
const given = [team, user, grant].filter((value) => value !== void 0);
|
|
419
|
+
if (given.length !== 1) {
|
|
420
|
+
throw new Error(
|
|
421
|
+
`Pass exactly one of ${allowGrant ? "--team, --user, or --grant" : "--team or --user"}.
|
|
422
|
+
${packageCollaboratorUsage}`
|
|
423
|
+
);
|
|
424
|
+
}
|
|
425
|
+
if (team) return { kind: "team", slug: team.replace(/^@/, "") };
|
|
426
|
+
if (user) return { kind: "user", username: user.replace(/^@/, "") };
|
|
427
|
+
return { kind: "grant", grantId: grant };
|
|
428
|
+
}
|
|
429
|
+
function readPreset(value) {
|
|
430
|
+
const preset = readFlag(value, "preset") ?? "use";
|
|
431
|
+
if (!packageCollaboratorPresets.includes(preset)) {
|
|
432
|
+
throw new Error(`--preset must be one of ${packageCollaboratorPresets.join(", ")}.`);
|
|
433
|
+
}
|
|
434
|
+
return preset;
|
|
435
|
+
}
|
|
436
|
+
function parsePackageCollaboratorCommand(input) {
|
|
437
|
+
const packageId = input.positionals[0]?.trim();
|
|
438
|
+
if (!packageId || input.positionals.length > 1) {
|
|
439
|
+
throw new Error(packageCollaboratorUsage);
|
|
440
|
+
}
|
|
441
|
+
switch (input.action) {
|
|
442
|
+
case "collaborators":
|
|
443
|
+
return { action: "collaborators", packageId };
|
|
444
|
+
case "grant": {
|
|
445
|
+
const subject = readSubject(input.values, false);
|
|
446
|
+
if (subject.kind === "grant") throw new Error(packageCollaboratorUsage);
|
|
447
|
+
return {
|
|
448
|
+
action: "grant",
|
|
449
|
+
packageId,
|
|
450
|
+
subject,
|
|
451
|
+
preset: readPreset(input.values.preset)
|
|
452
|
+
};
|
|
453
|
+
}
|
|
454
|
+
case "revoke":
|
|
455
|
+
if (input.values.preset !== void 0) {
|
|
456
|
+
throw new Error(`--preset is only for grant.
|
|
457
|
+
${packageCollaboratorUsage}`);
|
|
458
|
+
}
|
|
459
|
+
return { action: "revoke", packageId, target: readSubject(input.values, true) };
|
|
460
|
+
default: {
|
|
461
|
+
const exhaustive = input.action;
|
|
462
|
+
throw new Error(`Unhandled package action: ${String(exhaustive)}`);
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
function describeSubject(subject) {
|
|
467
|
+
return subject.kind === "team" ? `team ${subject.slug}` : `@${subject.username}`;
|
|
468
|
+
}
|
|
469
|
+
function collaboratorLabel(collaborator) {
|
|
470
|
+
if (collaborator.subject_type === "team") {
|
|
471
|
+
return collaborator.team_slug ? `${collaborator.team_slug}${collaborator.team_name ? ` (${collaborator.team_name})` : ""}` : collaborator.subject_id;
|
|
472
|
+
}
|
|
473
|
+
if (!collaborator.username) return collaborator.display_name ?? collaborator.subject_id;
|
|
474
|
+
return collaborator.display_name ? `@${collaborator.username} (${collaborator.display_name})` : `@${collaborator.username}`;
|
|
475
|
+
}
|
|
476
|
+
function presetLabel(collaborator) {
|
|
477
|
+
return collaborator.preset ?? `custom (${collaborator.permissions.length} permissions)`;
|
|
478
|
+
}
|
|
479
|
+
function formatCollaboratorList(list) {
|
|
480
|
+
const header = `${list.package.name} (${list.package.id})`;
|
|
481
|
+
if (list.collaborators.length === 0) {
|
|
482
|
+
return `${header}
|
|
483
|
+
No collaborators. Org owners always have full access.
|
|
484
|
+
`;
|
|
485
|
+
}
|
|
486
|
+
const rows = list.collaborators.map((collaborator) => [
|
|
487
|
+
collaborator.kind,
|
|
488
|
+
collaboratorLabel(collaborator),
|
|
489
|
+
presetLabel(collaborator),
|
|
490
|
+
collaborator.grant_id
|
|
491
|
+
]);
|
|
492
|
+
const widths = [0, 1, 2].map(
|
|
493
|
+
(column) => Math.max(...rows.map((row) => row[column].length))
|
|
494
|
+
);
|
|
495
|
+
const lines = rows.map(
|
|
496
|
+
(row) => row.map((cell, column) => column < 3 ? cell.padEnd(widths[column]) : cell).join(" ")
|
|
497
|
+
);
|
|
498
|
+
return `${header}
|
|
499
|
+
${lines.join("\n")}
|
|
500
|
+
`;
|
|
501
|
+
}
|
|
502
|
+
function findCollaborator(list, subject) {
|
|
503
|
+
const match = list.collaborators.find(
|
|
504
|
+
(collaborator) => subject.kind === "team" ? collaborator.subject_type === "team" && collaborator.team_slug === subject.slug : collaborator.subject_type === "user" && collaborator.username?.toLowerCase() === subject.username.toLowerCase()
|
|
505
|
+
);
|
|
506
|
+
if (!match) {
|
|
507
|
+
throw new Error(`${describeSubject(subject)} is not a collaborator on ${list.package.name}.`);
|
|
508
|
+
}
|
|
509
|
+
return match;
|
|
510
|
+
}
|
|
511
|
+
async function runPackageCollaboratorPlan(input) {
|
|
512
|
+
const { plan, call, json } = input;
|
|
513
|
+
const print = (value, text) => json ? `${JSON.stringify(value, null, 2)}
|
|
514
|
+
` : text;
|
|
515
|
+
switch (plan.action) {
|
|
516
|
+
case "collaborators": {
|
|
517
|
+
const list = await call("packageCollaboratorList", {
|
|
518
|
+
package_id: plan.packageId
|
|
519
|
+
});
|
|
520
|
+
return print(list, formatCollaboratorList(list));
|
|
521
|
+
}
|
|
522
|
+
case "grant": {
|
|
523
|
+
const result = await call("packageCollaboratorSet", {
|
|
524
|
+
package_id: plan.packageId,
|
|
525
|
+
...plan.subject.kind === "team" ? { team_slug: plan.subject.slug } : { username: plan.subject.username },
|
|
526
|
+
preset: plan.preset
|
|
527
|
+
});
|
|
528
|
+
return print(
|
|
529
|
+
result,
|
|
530
|
+
`${collaboratorLabel(result.collaborator)} now has ${presetLabel(result.collaborator)} on ${result.package.name} (grant ${result.collaborator.grant_id}).
|
|
531
|
+
`
|
|
532
|
+
);
|
|
533
|
+
}
|
|
534
|
+
case "revoke": {
|
|
535
|
+
const target = plan.target;
|
|
536
|
+
let grantId;
|
|
537
|
+
let label;
|
|
538
|
+
let packageName = plan.packageId;
|
|
539
|
+
if (target.kind === "grant") {
|
|
540
|
+
grantId = target.grantId;
|
|
541
|
+
label = `grant ${grantId}`;
|
|
542
|
+
} else {
|
|
543
|
+
const list = await call("packageCollaboratorList", {
|
|
544
|
+
package_id: plan.packageId
|
|
545
|
+
});
|
|
546
|
+
const collaborator = findCollaborator(list, target);
|
|
547
|
+
grantId = collaborator.grant_id;
|
|
548
|
+
label = collaboratorLabel(collaborator);
|
|
549
|
+
packageName = list.package.name;
|
|
550
|
+
}
|
|
551
|
+
const result = await call("packageCollaboratorRemove", {
|
|
552
|
+
package_id: plan.packageId,
|
|
553
|
+
grant_id: grantId
|
|
554
|
+
});
|
|
555
|
+
return print(result, `Removed ${label} from ${packageName}.
|
|
556
|
+
`);
|
|
557
|
+
}
|
|
558
|
+
default: {
|
|
559
|
+
const exhaustive = plan;
|
|
560
|
+
throw new Error(`Unhandled package plan: ${JSON.stringify(exhaustive)}`);
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
// src/cli.ts
|
|
566
|
+
var orgScopedCommands = /* @__PURE__ */ new Set([
|
|
567
|
+
"login",
|
|
568
|
+
"logout",
|
|
569
|
+
"whoami",
|
|
570
|
+
"search",
|
|
571
|
+
"api",
|
|
572
|
+
"package",
|
|
573
|
+
"execute",
|
|
574
|
+
"dev",
|
|
575
|
+
"auth"
|
|
576
|
+
]);
|
|
577
|
+
function mcpUrlFrom(values) {
|
|
578
|
+
return values.mcpUrl || process.env.KODY_MCP_URL || defaultMcpUrl;
|
|
579
|
+
}
|
|
580
|
+
function apiUrlFrom(values, env = process.env) {
|
|
581
|
+
return values.apiUrl || env.KODY_API_URL || defaultApiUrl;
|
|
582
|
+
}
|
|
583
|
+
function parseKnown(args) {
|
|
584
|
+
return parseArgs({
|
|
585
|
+
args,
|
|
586
|
+
allowPositionals: true,
|
|
587
|
+
strict: false,
|
|
588
|
+
options: {
|
|
589
|
+
help: { type: "boolean", short: "h" },
|
|
590
|
+
version: { type: "boolean", short: "v" },
|
|
591
|
+
json: { type: "boolean" },
|
|
592
|
+
"mcp-url": { type: "string" },
|
|
593
|
+
entity: { type: "string" },
|
|
594
|
+
domain: { type: "string" },
|
|
595
|
+
limit: { type: "string" },
|
|
596
|
+
code: { type: "string" },
|
|
597
|
+
file: { type: "string" },
|
|
598
|
+
invoke: { type: "string" },
|
|
599
|
+
params: { type: "string" },
|
|
600
|
+
"conversation-id": { type: "string" },
|
|
601
|
+
local: { type: "boolean" },
|
|
602
|
+
"allow-private-network": { type: "boolean" },
|
|
603
|
+
credential: { type: "string", multiple: true },
|
|
604
|
+
token: { type: "string" },
|
|
605
|
+
"api-url": { type: "string" },
|
|
606
|
+
lifetime: { type: "string" },
|
|
607
|
+
"idle-ttl-seconds": { type: "string" },
|
|
608
|
+
"max-lifetime-seconds": { type: "string" },
|
|
609
|
+
scopes: { type: "string" },
|
|
610
|
+
project: { type: "boolean" },
|
|
611
|
+
"no-browser": { type: "boolean" },
|
|
612
|
+
org: { type: "string" },
|
|
613
|
+
target: { type: "string" },
|
|
614
|
+
"reset-storage": { type: "boolean" },
|
|
615
|
+
"dry-run": { type: "boolean" },
|
|
616
|
+
passthrough: { type: "string" },
|
|
617
|
+
port: { type: "string" },
|
|
618
|
+
"app-base-path": { type: "string" },
|
|
619
|
+
"no-live-reload": { type: "boolean" },
|
|
620
|
+
"ready-file": { type: "string" },
|
|
621
|
+
"no-attach": { type: "boolean" },
|
|
622
|
+
method: { type: "string" },
|
|
623
|
+
body: { type: "string" },
|
|
624
|
+
clients: { type: "string" },
|
|
625
|
+
yes: { type: "boolean", short: "y" },
|
|
626
|
+
team: { type: "string" },
|
|
627
|
+
user: { type: "string" },
|
|
628
|
+
preset: { type: "string" },
|
|
629
|
+
grant: { type: "string" }
|
|
630
|
+
}
|
|
631
|
+
});
|
|
632
|
+
}
|
|
633
|
+
function resolveCommand(argv) {
|
|
634
|
+
const { positionals, values } = parseKnown(argv);
|
|
635
|
+
if (values.help && positionals.length === 0) {
|
|
636
|
+
return { command: "help", positionals, values };
|
|
637
|
+
}
|
|
638
|
+
if (values.version && positionals.length === 0) {
|
|
639
|
+
return { command: "version", positionals, values };
|
|
640
|
+
}
|
|
641
|
+
const raw = positionals[0];
|
|
642
|
+
if (!raw) return { command: "help", positionals, values };
|
|
643
|
+
switch (raw) {
|
|
644
|
+
case "login":
|
|
645
|
+
case "logout":
|
|
646
|
+
case "org":
|
|
647
|
+
case "status":
|
|
648
|
+
case "auth":
|
|
649
|
+
case "git-credential":
|
|
650
|
+
case "whoami":
|
|
651
|
+
case "search":
|
|
652
|
+
case "api":
|
|
653
|
+
case "package":
|
|
654
|
+
case "execute":
|
|
655
|
+
case "dev":
|
|
656
|
+
case "install":
|
|
657
|
+
case "skill":
|
|
658
|
+
case "help":
|
|
659
|
+
case "version":
|
|
660
|
+
return { command: raw, positionals: positionals.slice(1), values };
|
|
661
|
+
default:
|
|
662
|
+
throw new Error(
|
|
663
|
+
`Unknown command "${raw}". Run \`kody --help\` for usage.`
|
|
664
|
+
);
|
|
665
|
+
}
|
|
666
|
+
}
|
|
667
|
+
async function runCli(argv = process.argv.slice(2), io = {}) {
|
|
668
|
+
const write = io.stdout ?? ((text) => process.stdout.write(text));
|
|
669
|
+
const writeErr = io.stderr ?? ((text) => process.stderr.write(text));
|
|
670
|
+
const head = argv[0];
|
|
671
|
+
const skipHelperRefresh = process.env.NODE_TEST === "1" || process.env.KODY_SKIP_GIT_HELPER_REFRESH === "1" || head === "git-credential" || head === "version" || head === "--version" || head === "-v" || head === "help" || head === "--help" || head === "-h" || head === void 0;
|
|
672
|
+
if (!skipHelperRefresh) {
|
|
673
|
+
try {
|
|
674
|
+
refreshGitCredentialHelperPinIfNeeded({
|
|
675
|
+
mcpUrl: process.env.KODY_MCP_URL || void 0
|
|
676
|
+
});
|
|
677
|
+
} catch {
|
|
678
|
+
}
|
|
679
|
+
}
|
|
680
|
+
try {
|
|
681
|
+
const parsed = resolveCommand(argv);
|
|
682
|
+
const helpMcpUrl = mcpUrlFrom({
|
|
683
|
+
mcpUrl: typeof parsed.values["mcp-url"] === "string" ? parsed.values["mcp-url"] : void 0
|
|
684
|
+
});
|
|
685
|
+
if (parsed.values.help && parsed.command !== "help") {
|
|
686
|
+
write(buildUsage({ mcpUrl: helpMcpUrl }));
|
|
687
|
+
return 0;
|
|
688
|
+
}
|
|
689
|
+
return await dispatch(parsed, write, writeErr);
|
|
690
|
+
} catch (error) {
|
|
691
|
+
writeErr(`${redactError(error).message}
|
|
692
|
+
`);
|
|
693
|
+
return 1;
|
|
694
|
+
}
|
|
695
|
+
}
|
|
696
|
+
async function dispatch(parsed, write, writeErr) {
|
|
697
|
+
const mcpUrl = mcpUrlFrom({
|
|
698
|
+
mcpUrl: typeof parsed.values["mcp-url"] === "string" ? parsed.values["mcp-url"] : void 0
|
|
699
|
+
});
|
|
700
|
+
const json = parsed.values.json === true;
|
|
701
|
+
if (parsed.values["allow-private-network"] === true) {
|
|
702
|
+
const executeAllowsPrivateNetwork = parsed.command === "execute" && (parsed.values.local === true || (await import("./target-3QHY7JT4.js")).resolveTarget({
|
|
703
|
+
command: "execute",
|
|
704
|
+
flag: typeof parsed.values.target === "string" ? parsed.values.target : void 0
|
|
705
|
+
}) === "mock");
|
|
706
|
+
if (parsed.command !== "dev" && !executeAllowsPrivateNetwork) {
|
|
707
|
+
throw new Error(
|
|
708
|
+
"--allow-private-network can only be used with execute --local, execute --target mock, or kody dev."
|
|
709
|
+
);
|
|
710
|
+
}
|
|
711
|
+
}
|
|
712
|
+
if (parsed.values["reset-storage"] === true && parsed.command !== "dev" && parsed.command !== "execute" && parsed.command !== "search") {
|
|
713
|
+
throw new Error("`--reset-storage` is only used with --target mock on execute, search, or dev.");
|
|
714
|
+
}
|
|
715
|
+
if (parsed.values["dry-run"] === true && parsed.command !== "dev") {
|
|
716
|
+
throw new Error(
|
|
717
|
+
"`--dry-run` is only used with `kody dev job|webhook|emit` (shows the plan without invoking)."
|
|
718
|
+
);
|
|
719
|
+
}
|
|
720
|
+
if (typeof parsed.values.passthrough === "string" && parsed.command !== "dev" && parsed.command !== "execute") {
|
|
721
|
+
throw new Error(
|
|
722
|
+
"`--passthrough` is only used with `execute --target mock` or `kody dev` when `.kody/mocks.ts` is active."
|
|
723
|
+
);
|
|
724
|
+
}
|
|
725
|
+
const orgFlag = typeof parsed.values.org === "string" ? parsed.values.org : void 0;
|
|
726
|
+
if (orgFlag !== void 0 && !orgScopedCommands.has(parsed.command)) {
|
|
727
|
+
throw new Error(
|
|
728
|
+
`\`--org\` is not used with \`kody ${parsed.command}\`. Use it with login, logout, whoami, search, api, package, execute, or auth.`
|
|
729
|
+
);
|
|
730
|
+
}
|
|
731
|
+
const orgFlagOnly = orgFlag !== void 0 ? orgSlugFromFlag(orgFlag) : void 0;
|
|
732
|
+
const org = resolveOrgSlug({ flag: orgFlag });
|
|
733
|
+
switch (parsed.command) {
|
|
734
|
+
case "help":
|
|
735
|
+
write(buildUsage({ mcpUrl }));
|
|
736
|
+
return 0;
|
|
737
|
+
case "version":
|
|
738
|
+
write(`${readPackageVersion()}
|
|
739
|
+
`);
|
|
740
|
+
return 0;
|
|
741
|
+
case "login": {
|
|
742
|
+
const { login } = await import("./auth-4FW6GCLG.js");
|
|
743
|
+
write("Opening the Kody login page in your browser\u2026\n");
|
|
744
|
+
const result = await login({
|
|
745
|
+
mcpUrl,
|
|
746
|
+
...orgFlagOnly ? { org: orgFlagOnly } : {},
|
|
747
|
+
openBrowser: parsed.values["no-browser"] !== true,
|
|
748
|
+
onAuthorizationUrl: (url) => {
|
|
749
|
+
write(`If the browser does not open, visit:
|
|
750
|
+
${url.href}
|
|
751
|
+
`);
|
|
752
|
+
}
|
|
753
|
+
});
|
|
754
|
+
const orgLabel = result.org ? ` as org ${result.org}` : result.credentials.org ? ` as org ${result.credentials.org}` : "";
|
|
755
|
+
const accountLabel = result.account?.email ? ` (${result.account.email})` : result.account?.displayName ? ` (${result.account.displayName})` : "";
|
|
756
|
+
write(`Logged in to ${result.credentials.mcpUrl}${orgLabel}${accountLabel}.
|
|
757
|
+
`);
|
|
758
|
+
if (result.backendKind === "file" && result.backendPath) {
|
|
759
|
+
write(
|
|
760
|
+
`OS keychain was unavailable; credentials saved at ${result.backendPath} (mode 0600).
|
|
761
|
+
`
|
|
762
|
+
);
|
|
763
|
+
} else {
|
|
764
|
+
write("Credentials stored in the OS keychain.\n");
|
|
765
|
+
}
|
|
766
|
+
return 0;
|
|
767
|
+
}
|
|
768
|
+
case "logout": {
|
|
769
|
+
const apiUrl = apiUrlFrom({
|
|
770
|
+
apiUrl: typeof parsed.values["api-url"] === "string" ? parsed.values["api-url"] : void 0
|
|
771
|
+
});
|
|
772
|
+
const oauth = deleteCredentials(
|
|
773
|
+
mcpUrl,
|
|
774
|
+
void 0,
|
|
775
|
+
void 0,
|
|
776
|
+
orgFlagOnly ? { org: orgFlagOnly } : void 0
|
|
777
|
+
);
|
|
778
|
+
const clearApiToken = !orgFlagOnly || oauth.remaining === 0;
|
|
779
|
+
const apiToken = clearApiToken ? deleteStoredApiToken(apiUrl) : { deleted: false };
|
|
780
|
+
if (!oauth.deleted && !apiToken.deleted) {
|
|
781
|
+
write(
|
|
782
|
+
orgFlagOnly ? `No stored login for org "${orgFlagOnly}".
|
|
783
|
+
` : "No stored credentials.\n"
|
|
784
|
+
);
|
|
785
|
+
return 0;
|
|
786
|
+
}
|
|
787
|
+
const parts = [];
|
|
788
|
+
if (oauth.deleted) {
|
|
789
|
+
parts.push(
|
|
790
|
+
orgFlagOnly ? `Logged out of org ${orgFlagOnly}.` : "Logged out of the active org (kody login)."
|
|
791
|
+
);
|
|
792
|
+
}
|
|
793
|
+
if (apiToken.deleted) parts.push("Cleared stored bootstrap/API token.");
|
|
794
|
+
write(`${parts.join(" ")}
|
|
795
|
+
`);
|
|
796
|
+
return 0;
|
|
797
|
+
}
|
|
798
|
+
case "org": {
|
|
799
|
+
const {
|
|
800
|
+
chooseOrgInteractively,
|
|
801
|
+
formatOrgListHuman,
|
|
802
|
+
formatOrgListJson,
|
|
803
|
+
useOrg
|
|
804
|
+
} = await import("./org-X7B5BI4R.js");
|
|
805
|
+
const { listStoredOrgs: listStoredOrgs2 } = await import("./store-WTMRH527.js");
|
|
806
|
+
const action = parsed.positionals[0];
|
|
807
|
+
if (action === "list") {
|
|
808
|
+
const orgs = listStoredOrgs2(mcpUrl);
|
|
809
|
+
write(json ? formatOrgListJson(orgs) : formatOrgListHuman(orgs));
|
|
810
|
+
return orgs.length === 0 ? 1 : 0;
|
|
811
|
+
}
|
|
812
|
+
if (action === "use") {
|
|
813
|
+
const slugArg = parsed.positionals[1];
|
|
814
|
+
if (slugArg) {
|
|
815
|
+
const next2 = useOrg(slugArg, mcpUrl);
|
|
816
|
+
write(`Active org is now ${next2.activeOrg}.
|
|
817
|
+
`);
|
|
818
|
+
return 0;
|
|
819
|
+
}
|
|
820
|
+
const orgs = listStoredOrgs2(mcpUrl);
|
|
821
|
+
const chosen = await chooseOrgInteractively({ orgs });
|
|
822
|
+
const next = useOrg(chosen, mcpUrl);
|
|
823
|
+
write(`Active org is now ${next.activeOrg}.
|
|
824
|
+
`);
|
|
825
|
+
return 0;
|
|
826
|
+
}
|
|
827
|
+
throw new Error("Usage: kody org list [--json] | kody org use [<slug>]");
|
|
828
|
+
}
|
|
829
|
+
case "status": {
|
|
830
|
+
const apiUrl = apiUrlFrom({
|
|
831
|
+
apiUrl: typeof parsed.values["api-url"] === "string" ? parsed.values["api-url"] : void 0
|
|
832
|
+
});
|
|
833
|
+
const credentials = loadCredentials(mcpUrl);
|
|
834
|
+
const orgs = listStoredOrgs(mcpUrl);
|
|
835
|
+
const storedApi = loadStoredApiToken(apiUrl);
|
|
836
|
+
if (!credentials && orgs.length === 0 && !storedApi) {
|
|
837
|
+
write("Not logged in.\n");
|
|
838
|
+
return 1;
|
|
839
|
+
}
|
|
840
|
+
const lines = [];
|
|
841
|
+
if (credentials || orgs.length > 0) {
|
|
842
|
+
const expires = credentials?.expiresAt ? new Date(credentials.expiresAt).toISOString() : "unknown";
|
|
843
|
+
lines.push(
|
|
844
|
+
`mcp: ${credentials?.mcpUrl ?? mcpUrl}`,
|
|
845
|
+
`logged in: yes`,
|
|
846
|
+
`active org: ${credentials?.org ?? orgs.find((row) => row.active)?.slug ?? "(pending)"}`,
|
|
847
|
+
`orgs: ${orgs.map((row) => row.active ? `${row.slug}*` : row.slug).join(", ") || "(pending)"}`,
|
|
848
|
+
`access token expires: ${expires}`,
|
|
849
|
+
`refresh token: ${credentials?.refreshToken ? "yes" : "no"}`,
|
|
850
|
+
`scope: ${credentials?.scope ?? "unknown"}`
|
|
851
|
+
);
|
|
852
|
+
} else {
|
|
853
|
+
lines.push(`mcp: ${mcpUrl}`, `logged in: no`);
|
|
854
|
+
}
|
|
855
|
+
if (storedApi) {
|
|
856
|
+
const scopes = storedApi.scopes?.join(", ") || "(unknown)";
|
|
857
|
+
lines.push(
|
|
858
|
+
`api: ${storedApi.apiUrl}`,
|
|
859
|
+
`stored API token: yes (${storedApi.tokenId})`,
|
|
860
|
+
`API token scopes: ${scopes}`,
|
|
861
|
+
`API token expires: ${storedApi.expiresAt ?? "unknown"}`,
|
|
862
|
+
`API token via: ${storedApi.createdVia ?? "unknown"}`
|
|
863
|
+
);
|
|
864
|
+
} else {
|
|
865
|
+
lines.push(`api: ${apiUrl}`, `stored API token: no`);
|
|
866
|
+
}
|
|
867
|
+
lines.push("");
|
|
868
|
+
write(lines.join("\n"));
|
|
869
|
+
return 0;
|
|
870
|
+
}
|
|
871
|
+
case "auth": {
|
|
872
|
+
const action = parsed.positionals[0];
|
|
873
|
+
if (action === "setup-git") {
|
|
874
|
+
return runAuthSetupGit({
|
|
875
|
+
values: parsed.values,
|
|
876
|
+
mcpUrl,
|
|
877
|
+
write,
|
|
878
|
+
...org ? { org } : {}
|
|
879
|
+
});
|
|
880
|
+
}
|
|
881
|
+
if (action === "remove-git") {
|
|
882
|
+
return runAuthRemoveGit({
|
|
883
|
+
values: parsed.values,
|
|
884
|
+
mcpUrl,
|
|
885
|
+
write
|
|
886
|
+
});
|
|
887
|
+
}
|
|
888
|
+
if (action !== "bootstrap") {
|
|
889
|
+
throw new Error(
|
|
890
|
+
"Usage: kody auth bootstrap (\u2026) | kody auth setup-git [\u2026] | kody auth remove-git [--api-url <url>] [--mcp-url <url>]"
|
|
891
|
+
);
|
|
892
|
+
}
|
|
893
|
+
const code = typeof parsed.values.code === "string" ? parsed.values.code.trim() : "";
|
|
894
|
+
const scopes = parseCliScopesFlag(
|
|
895
|
+
typeof parsed.values.scopes === "string" ? parsed.values.scopes : void 0
|
|
896
|
+
);
|
|
897
|
+
if (!code && !scopes) {
|
|
898
|
+
throw new Error(
|
|
899
|
+
"Provide --code <kody_bc_\u2026> from cliCredentialBootstrap (MCP api / kody.cliCredentialBootstrap), or --scopes <list> to mint one with the current kody login session or API token."
|
|
900
|
+
);
|
|
901
|
+
}
|
|
902
|
+
const lifetime = resolveCliTokenLifetime({
|
|
903
|
+
lifetime: typeof parsed.values.lifetime === "string" ? parsed.values.lifetime : void 0,
|
|
904
|
+
idleTtlSeconds: parseCliLifetimeSecondsFlag(
|
|
905
|
+
typeof parsed.values["idle-ttl-seconds"] === "string" ? parsed.values["idle-ttl-seconds"] : void 0,
|
|
906
|
+
"--idle-ttl-seconds"
|
|
907
|
+
),
|
|
908
|
+
maxLifetimeSeconds: parseCliLifetimeSecondsFlag(
|
|
909
|
+
typeof parsed.values["max-lifetime-seconds"] === "string" ? parsed.values["max-lifetime-seconds"] : void 0,
|
|
910
|
+
"--max-lifetime-seconds"
|
|
911
|
+
)
|
|
912
|
+
});
|
|
913
|
+
const apiUrl = apiUrlFrom({
|
|
914
|
+
apiUrl: typeof parsed.values["api-url"] === "string" ? parsed.values["api-url"] : void 0
|
|
915
|
+
});
|
|
916
|
+
if (code && scopes) {
|
|
917
|
+
throw new Error(
|
|
918
|
+
`--scopes cannot change a bootstrap code: its scopes are fixed when it is minted. From Kody MCP, call \`${cliBootstrapMintCall(scopes, bootstrapMintLifetimeFields(lifetime))}\` and redeem the new code, or drop --code to mint with the current kody login session or API token.`
|
|
919
|
+
);
|
|
920
|
+
}
|
|
921
|
+
const result = scopes ? await authBootstrapWithScopes({
|
|
922
|
+
scopes,
|
|
923
|
+
lifetime,
|
|
924
|
+
apiUrl,
|
|
925
|
+
mint: bootstrapMinter({
|
|
926
|
+
scopes,
|
|
927
|
+
lifetime,
|
|
928
|
+
mcpUrl,
|
|
929
|
+
apiUrl,
|
|
930
|
+
tokenValues: tokenFlagValues(parsed.values),
|
|
931
|
+
...org ? { org } : {}
|
|
932
|
+
})
|
|
933
|
+
}) : await authBootstrap({
|
|
934
|
+
code,
|
|
935
|
+
apiUrl,
|
|
936
|
+
...lifetime.kind === "alias" ? { lifetime: lifetime.lifetime } : {
|
|
937
|
+
idleTtlSeconds: lifetime.idleTtlSeconds,
|
|
938
|
+
maxLifetimeSeconds: lifetime.maxLifetimeSeconds
|
|
939
|
+
}
|
|
940
|
+
});
|
|
941
|
+
const storedScopes = result.stored.scopes?.join(", ") || "(none)";
|
|
942
|
+
write(
|
|
943
|
+
[
|
|
944
|
+
`Bootstrap API token stored for execute --local, search, whoami, api, and token-auth cloud execute.`,
|
|
945
|
+
`api: ${result.stored.apiUrl}`,
|
|
946
|
+
`token id: ${result.stored.tokenId}`,
|
|
947
|
+
`scopes: ${storedScopes}`,
|
|
948
|
+
`expires: ${result.stored.expiresAt ?? "unknown"}`,
|
|
949
|
+
result.backendKind === "file" && result.backendPath ? `OS keychain was unavailable; token saved at ${result.backendPath} (mode 0600).` : "Token stored in the OS keychain.",
|
|
950
|
+
""
|
|
951
|
+
].join("\n")
|
|
952
|
+
);
|
|
953
|
+
return 0;
|
|
954
|
+
}
|
|
955
|
+
case "git-credential": {
|
|
956
|
+
const {
|
|
957
|
+
handleGitCredential,
|
|
958
|
+
parseGitCredentialAction,
|
|
959
|
+
parseGitCredentialInput,
|
|
960
|
+
readGitCredentialStdin
|
|
961
|
+
} = await import("./git-credential-FUE3JE3T.js");
|
|
962
|
+
const action = parseGitCredentialAction(parsed.positionals);
|
|
963
|
+
const raw = await readGitCredentialStdin(process.stdin);
|
|
964
|
+
const output = await handleGitCredential({
|
|
965
|
+
action,
|
|
966
|
+
request: parseGitCredentialInput(raw),
|
|
967
|
+
apiUrl: apiUrlFrom({
|
|
968
|
+
apiUrl: typeof parsed.values["api-url"] === "string" ? parsed.values["api-url"] : void 0
|
|
969
|
+
}),
|
|
970
|
+
mcpUrl
|
|
971
|
+
});
|
|
972
|
+
if (output) process.stdout.write(output);
|
|
973
|
+
return 0;
|
|
974
|
+
}
|
|
975
|
+
case "whoami": {
|
|
976
|
+
const { resolveTarget } = await import("./target-3QHY7JT4.js");
|
|
977
|
+
const target = resolveTarget({
|
|
978
|
+
command: "whoami",
|
|
979
|
+
flag: typeof parsed.values.target === "string" ? parsed.values.target : void 0
|
|
980
|
+
});
|
|
981
|
+
const tokenValues = tokenFlagValues(parsed.values);
|
|
982
|
+
let apiUrl = apiUrlFrom({
|
|
983
|
+
apiUrl: typeof parsed.values["api-url"] === "string" ? parsed.values["api-url"] : void 0
|
|
984
|
+
});
|
|
985
|
+
if (target === "mock") {
|
|
986
|
+
const { ensureMockTarget } = await import("./mock-server-SV2IKC4I.js");
|
|
987
|
+
const mock = await ensureMockTarget({
|
|
988
|
+
resetStorage: parsed.values["reset-storage"] === true,
|
|
989
|
+
...org ? { orgSlug: org } : {}
|
|
990
|
+
});
|
|
991
|
+
try {
|
|
992
|
+
const me = await fetch(`${mock.apiUrl}/v1/me${org ? `?org=${encodeURIComponent(org)}` : ""}`, {
|
|
993
|
+
headers: { authorization: `Bearer ${mock.token}` }
|
|
994
|
+
});
|
|
995
|
+
const body = await me.json();
|
|
996
|
+
if (json) {
|
|
997
|
+
write(`${JSON.stringify({ target: "mock", ...body }, null, 2)}
|
|
998
|
+
`);
|
|
999
|
+
} else {
|
|
1000
|
+
const userId = typeof body.user_id === "string" ? body.user_id : "user_mock";
|
|
1001
|
+
const username = typeof body.username === "string" ? body.username : "mock-user";
|
|
1002
|
+
const orgBody = body.org && typeof body.org === "object" ? body.org : {};
|
|
1003
|
+
write(
|
|
1004
|
+
[
|
|
1005
|
+
`target: mock`,
|
|
1006
|
+
`api: ${mock.apiUrl}`,
|
|
1007
|
+
`user: ${username} (${userId})`,
|
|
1008
|
+
`org: ${orgBody.slug ?? org ?? "mock-org"}`,
|
|
1009
|
+
""
|
|
1010
|
+
].join("\n")
|
|
1011
|
+
);
|
|
1012
|
+
}
|
|
1013
|
+
return me.ok ? 0 : 1;
|
|
1014
|
+
} finally {
|
|
1015
|
+
if (mock.started) await mock.server.close();
|
|
1016
|
+
}
|
|
1017
|
+
}
|
|
1018
|
+
if (shouldUseApiToken({
|
|
1019
|
+
tokenValues,
|
|
1020
|
+
mcpUrl,
|
|
1021
|
+
apiUrl,
|
|
1022
|
+
allowEnvWithoutLogin: true,
|
|
1023
|
+
...org ? { org } : {}
|
|
1024
|
+
})) {
|
|
1025
|
+
const { whoamiWithApiToken } = await import("./open-api-client-DVVMLY7P.js");
|
|
1026
|
+
const identity = await whoamiWithApiToken({
|
|
1027
|
+
token: requireApiToken(tokenValues, process.env, "whoami", { apiUrl }),
|
|
1028
|
+
apiUrl,
|
|
1029
|
+
...org ? { org } : {}
|
|
1030
|
+
});
|
|
1031
|
+
if (json) {
|
|
1032
|
+
write(`${JSON.stringify(identity, null, 2)}
|
|
1033
|
+
`);
|
|
1034
|
+
return 0;
|
|
1035
|
+
}
|
|
1036
|
+
const scopeLine = identity.token.scopes.join(", ") || "(none)";
|
|
1037
|
+
const userLine = identity.user ? `${identity.user.displayName} <${identity.user.email}>` : "(account:read not on this token)";
|
|
1038
|
+
write(
|
|
1039
|
+
[
|
|
1040
|
+
`api: ${identity.apiUrl}`,
|
|
1041
|
+
`auth: API token (${identity.token.id})`,
|
|
1042
|
+
`user: ${userLine}`,
|
|
1043
|
+
`scopes: ${scopeLine}`,
|
|
1044
|
+
`expires: ${identity.token.expiresAt ?? "unknown"}`,
|
|
1045
|
+
""
|
|
1046
|
+
].join("\n")
|
|
1047
|
+
);
|
|
1048
|
+
return 0;
|
|
1049
|
+
}
|
|
1050
|
+
const [{ ensureFreshCredentials }, { listKodyTools }] = await Promise.all([
|
|
1051
|
+
import("./auth-4FW6GCLG.js"),
|
|
1052
|
+
import("./mcp-G2AWTIXR.js")
|
|
1053
|
+
]);
|
|
1054
|
+
const credentials = await ensureFreshCredentials({ mcpUrl, org });
|
|
1055
|
+
const tools = await listKodyTools({ mcpUrl, org });
|
|
1056
|
+
if (json) {
|
|
1057
|
+
write(
|
|
1058
|
+
`${JSON.stringify(
|
|
1059
|
+
{
|
|
1060
|
+
mcpUrl: credentials.mcpUrl,
|
|
1061
|
+
org: credentials.org ?? null,
|
|
1062
|
+
protocol: modernMcpProtocolVersion,
|
|
1063
|
+
scope: credentials.scope ?? null,
|
|
1064
|
+
tools: tools.map((tool) => tool.name)
|
|
1065
|
+
},
|
|
1066
|
+
null,
|
|
1067
|
+
2
|
|
1068
|
+
)}
|
|
1069
|
+
`
|
|
1070
|
+
);
|
|
1071
|
+
return 0;
|
|
1072
|
+
}
|
|
1073
|
+
const orgLine = credentials.org ? `
|
|
1074
|
+
org: ${credentials.org}` : "";
|
|
1075
|
+
write(
|
|
1076
|
+
`Connected to ${credentials.mcpUrl} (${modernMcpProtocolVersion})${orgLine}
|
|
1077
|
+
Tools: ${tools.map((tool) => tool.name).join(", ") || "(none)"}
|
|
1078
|
+
`
|
|
1079
|
+
);
|
|
1080
|
+
return 0;
|
|
1081
|
+
}
|
|
1082
|
+
case "search": {
|
|
1083
|
+
const { resolveTarget } = await import("./target-3QHY7JT4.js");
|
|
1084
|
+
const target = resolveTarget({
|
|
1085
|
+
command: "search",
|
|
1086
|
+
flag: typeof parsed.values.target === "string" ? parsed.values.target : void 0
|
|
1087
|
+
});
|
|
1088
|
+
const query = parsed.positionals.join(" ").trim();
|
|
1089
|
+
const tokenValues = tokenFlagValues(parsed.values);
|
|
1090
|
+
let apiUrl = apiUrlFrom({
|
|
1091
|
+
apiUrl: typeof parsed.values["api-url"] === "string" ? parsed.values["api-url"] : void 0
|
|
1092
|
+
});
|
|
1093
|
+
let closeMock;
|
|
1094
|
+
try {
|
|
1095
|
+
if (target === "mock") {
|
|
1096
|
+
const { ensureMockTarget } = await import("./mock-server-SV2IKC4I.js");
|
|
1097
|
+
const mock = await ensureMockTarget({
|
|
1098
|
+
resetStorage: parsed.values["reset-storage"] === true
|
|
1099
|
+
});
|
|
1100
|
+
apiUrl = mock.apiUrl;
|
|
1101
|
+
closeMock = mock.started ? () => mock.server.close() : void 0;
|
|
1102
|
+
const { searchWithApiToken } = await import("./open-api-client-DVVMLY7P.js");
|
|
1103
|
+
const result2 = await searchWithApiToken({
|
|
1104
|
+
token: mock.token,
|
|
1105
|
+
apiUrl,
|
|
1106
|
+
query: query || void 0,
|
|
1107
|
+
entity: typeof parsed.values.entity === "string" ? parsed.values.entity : void 0,
|
|
1108
|
+
domain: typeof parsed.values.domain === "string" ? parsed.values.domain : void 0,
|
|
1109
|
+
limit: typeof parsed.values.limit === "string" ? Number(parsed.values.limit) : void 0
|
|
1110
|
+
});
|
|
1111
|
+
write(formatToolResult(result2, json));
|
|
1112
|
+
return result2.isError ? 1 : 0;
|
|
1113
|
+
}
|
|
1114
|
+
if (shouldUseApiToken({
|
|
1115
|
+
tokenValues,
|
|
1116
|
+
mcpUrl,
|
|
1117
|
+
apiUrl,
|
|
1118
|
+
allowEnvWithoutLogin: true,
|
|
1119
|
+
...org ? { org } : {}
|
|
1120
|
+
})) {
|
|
1121
|
+
const { searchWithApiToken } = await import("./open-api-client-DVVMLY7P.js");
|
|
1122
|
+
const result2 = await searchWithApiToken({
|
|
1123
|
+
token: requireApiToken(tokenValues, process.env, "search", { apiUrl }),
|
|
1124
|
+
apiUrl,
|
|
1125
|
+
...org ? { org } : {},
|
|
1126
|
+
query: query || void 0,
|
|
1127
|
+
entity: typeof parsed.values.entity === "string" ? parsed.values.entity : void 0,
|
|
1128
|
+
domain: typeof parsed.values.domain === "string" ? parsed.values.domain : void 0,
|
|
1129
|
+
limit: typeof parsed.values.limit === "string" ? Number(parsed.values.limit) : void 0
|
|
1130
|
+
});
|
|
1131
|
+
write(formatToolResult(result2, json));
|
|
1132
|
+
return result2.isError ? 1 : 0;
|
|
1133
|
+
}
|
|
1134
|
+
const args = {};
|
|
1135
|
+
if (query) args.query = query;
|
|
1136
|
+
if (typeof parsed.values.entity === "string") args.entity = parsed.values.entity;
|
|
1137
|
+
if (typeof parsed.values.domain === "string") args.domain = parsed.values.domain;
|
|
1138
|
+
if (typeof parsed.values.limit === "string") args.limit = Number(parsed.values.limit);
|
|
1139
|
+
const { callKodyTool } = await import("./mcp-G2AWTIXR.js");
|
|
1140
|
+
const result = await callKodyTool({
|
|
1141
|
+
name: "search",
|
|
1142
|
+
args,
|
|
1143
|
+
mcpUrl,
|
|
1144
|
+
...org ? { org } : {}
|
|
1145
|
+
});
|
|
1146
|
+
write(formatToolResult(result, json));
|
|
1147
|
+
return result.isError ? 1 : 0;
|
|
1148
|
+
} finally {
|
|
1149
|
+
await closeMock?.();
|
|
1150
|
+
}
|
|
1151
|
+
}
|
|
1152
|
+
case "execute": {
|
|
1153
|
+
const { resolveTarget } = await import("./target-3QHY7JT4.js");
|
|
1154
|
+
const target = resolveTarget({
|
|
1155
|
+
command: "execute",
|
|
1156
|
+
flag: typeof parsed.values.target === "string" ? parsed.values.target : void 0
|
|
1157
|
+
});
|
|
1158
|
+
const invoke = typeof parsed.values.invoke === "string" ? parsed.values.invoke : void 0;
|
|
1159
|
+
const hasCodeFlag = typeof parsed.values.code === "string";
|
|
1160
|
+
const hasFileFlag = typeof parsed.values.file === "string";
|
|
1161
|
+
const positionalModule = parsed.positionals.join("\n").trim();
|
|
1162
|
+
const local = parsed.values.local === true || target === "mock";
|
|
1163
|
+
const tokenValues = tokenFlagValues(parsed.values);
|
|
1164
|
+
const localPackageInvoke = invoke !== void 0 ? await tryResolveLocalPackageInvoke(invoke) : null;
|
|
1165
|
+
let publishedInvokeCode;
|
|
1166
|
+
if (local && invoke !== void 0 && !localPackageInvoke) {
|
|
1167
|
+
try {
|
|
1168
|
+
publishedInvokeCode = resolveExecuteInvokeCode(invoke);
|
|
1169
|
+
} catch {
|
|
1170
|
+
throw new Error(
|
|
1171
|
+
`--invoke ${JSON.stringify(invoke)} is neither a local package export nor a published package specifier. From a package directory, pass an export key from package.json#exports (e.g. \`--invoke ./greet\`). To call a published export locally, use \`--invoke kody:@scope/pkg/export\` (or \`@scope/pkg#export\`) \u2014 no \`--code "import \u2026"\` wrapper needed. Or pass --code / --file / a module string.`
|
|
1172
|
+
);
|
|
1173
|
+
}
|
|
1174
|
+
}
|
|
1175
|
+
if (executeSourcesConflict({ invoke, hasCodeFlag, hasFileFlag, positionalModule })) {
|
|
1176
|
+
throw new Error(
|
|
1177
|
+
"--invoke cannot be combined with --code, --file, or a module string."
|
|
1178
|
+
);
|
|
1179
|
+
}
|
|
1180
|
+
if (local) assertLocalExecuteNodeEngine();
|
|
1181
|
+
const fileArg = hasFileFlag ? parsed.values.file : void 0;
|
|
1182
|
+
const modulePath = localPackageInvoke?.modulePath ?? (!hasCodeFlag && fileArg !== void 0 && fileArg !== "-" ? fileArg : void 0);
|
|
1183
|
+
const code = publishedInvokeCode !== void 0 ? publishedInvokeCode : invoke !== void 0 && !localPackageInvoke ? void 0 : hasCodeFlag ? parsed.values.code : modulePath !== void 0 && !localPackageInvoke ? await readFile(modulePath, "utf8") : localPackageInvoke ? await readFile(localPackageInvoke.modulePath, "utf8") : fileArg === "-" ? await readStdin() : positionalModule || void 0;
|
|
1184
|
+
const credentials = parseCredentialFlags(
|
|
1185
|
+
Array.isArray(parsed.values.credential) ? parsed.values.credential.filter(
|
|
1186
|
+
(value) => typeof value === "string"
|
|
1187
|
+
) : typeof parsed.values.credential === "string" ? [parsed.values.credential] : void 0
|
|
1188
|
+
);
|
|
1189
|
+
const args = buildExecuteToolArgs({
|
|
1190
|
+
// Local published invoke is already minted into `code`.
|
|
1191
|
+
invoke: localPackageInvoke || publishedInvokeCode !== void 0 ? void 0 : invoke,
|
|
1192
|
+
code: typeof code === "string" ? code : void 0,
|
|
1193
|
+
paramsJson: typeof parsed.values.params === "string" ? parsed.values.params : void 0,
|
|
1194
|
+
conversationId: typeof parsed.values["conversation-id"] === "string" ? parsed.values["conversation-id"] : void 0,
|
|
1195
|
+
credentials
|
|
1196
|
+
});
|
|
1197
|
+
const prodApiUrl = apiUrlFrom({
|
|
1198
|
+
apiUrl: typeof parsed.values["api-url"] === "string" ? parsed.values["api-url"] : void 0
|
|
1199
|
+
});
|
|
1200
|
+
let apiUrl = prodApiUrl;
|
|
1201
|
+
const { parsePassthroughHosts } = await import("./mock-fetch-gateway-B5TFGGQS.js");
|
|
1202
|
+
const passthroughHosts = parsePassthroughHosts(
|
|
1203
|
+
typeof parsed.values.passthrough === "string" ? parsed.values.passthrough : void 0
|
|
1204
|
+
);
|
|
1205
|
+
if (passthroughHosts.length > 0 && target !== "mock") {
|
|
1206
|
+
writeErr(
|
|
1207
|
+
"note: `--passthrough` is ignored on `--target prod` (outbound fetch mocking is mock-only).\n"
|
|
1208
|
+
);
|
|
1209
|
+
}
|
|
1210
|
+
let closeMock;
|
|
1211
|
+
let mockToken;
|
|
1212
|
+
let mockDepResolve;
|
|
1213
|
+
let localPackageRun = localPackageInvoke;
|
|
1214
|
+
if (!localPackageRun && local && modulePath !== void 0) {
|
|
1215
|
+
try {
|
|
1216
|
+
const { loadPackageManifest } = await import("./package-manifest-QH2RU64C.js");
|
|
1217
|
+
const manifest = await loadPackageManifest(process.cwd());
|
|
1218
|
+
localPackageRun = {
|
|
1219
|
+
modulePath,
|
|
1220
|
+
kodyId: manifest.kodyId,
|
|
1221
|
+
packageRoot: manifest.root
|
|
1222
|
+
};
|
|
1223
|
+
} catch {
|
|
1224
|
+
localPackageRun = null;
|
|
1225
|
+
}
|
|
1226
|
+
}
|
|
1227
|
+
try {
|
|
1228
|
+
if (target === "mock") {
|
|
1229
|
+
const { ensureMockTarget } = await import("./mock-server-SV2IKC4I.js");
|
|
1230
|
+
const mock = await ensureMockTarget({
|
|
1231
|
+
resetStorage: parsed.values["reset-storage"] === true,
|
|
1232
|
+
packageId: localPackageRun ? `local:${localPackageRun.kodyId}` : void 0,
|
|
1233
|
+
...org ? { orgSlug: org } : {}
|
|
1234
|
+
});
|
|
1235
|
+
apiUrl = mock.apiUrl;
|
|
1236
|
+
mockToken = mock.token;
|
|
1237
|
+
closeMock = mock.started ? () => mock.server.close() : void 0;
|
|
1238
|
+
const { tryResolveMockDepResolve } = await import("./mock-dep-resolve-TVABDNR7.js");
|
|
1239
|
+
mockDepResolve = await tryResolveMockDepResolve({
|
|
1240
|
+
tokenValues,
|
|
1241
|
+
apiUrl: prodApiUrl,
|
|
1242
|
+
mcpUrl,
|
|
1243
|
+
...org ? { org } : {}
|
|
1244
|
+
});
|
|
1245
|
+
}
|
|
1246
|
+
if (localPackageRun) {
|
|
1247
|
+
const { buildLocalPackageContext, runLocalPackageModule } = await import("./local-package-run-2TMCAZZ2.js");
|
|
1248
|
+
const result2 = await runLocalPackageModule({
|
|
1249
|
+
modulePath: localPackageRun.modulePath,
|
|
1250
|
+
params: args.params,
|
|
1251
|
+
token: mockToken ?? await resolveLocalExecuteBearer({
|
|
1252
|
+
tokenValues,
|
|
1253
|
+
mcpUrl,
|
|
1254
|
+
apiUrl,
|
|
1255
|
+
purpose: "execute local package export",
|
|
1256
|
+
...org ? { org } : {}
|
|
1257
|
+
}),
|
|
1258
|
+
apiUrl,
|
|
1259
|
+
target,
|
|
1260
|
+
packageContext: buildLocalPackageContext({
|
|
1261
|
+
kodyId: localPackageRun.kodyId,
|
|
1262
|
+
hostedUrl: "http://127.0.0.1:0"
|
|
1263
|
+
}),
|
|
1264
|
+
packageRoot: localPackageRun.packageRoot,
|
|
1265
|
+
...org ? { org } : {},
|
|
1266
|
+
...mockDepResolve ? { depResolve: mockDepResolve } : {},
|
|
1267
|
+
...passthroughHosts.length > 0 && target === "mock" ? { passthroughHosts } : {},
|
|
1268
|
+
allowPrivateNetwork: parsed.values["allow-private-network"] === true,
|
|
1269
|
+
onStatus: (message) => writeErr(`${message}
|
|
1270
|
+
`)
|
|
1271
|
+
});
|
|
1272
|
+
write(formatToolResult(result2, json));
|
|
1273
|
+
return result2.isError ? 1 : 0;
|
|
1274
|
+
}
|
|
1275
|
+
const useToken = local || shouldUseApiToken({
|
|
1276
|
+
tokenValues,
|
|
1277
|
+
mcpUrl,
|
|
1278
|
+
apiUrl,
|
|
1279
|
+
allowEnvWithoutLogin: true,
|
|
1280
|
+
...org ? { org } : {}
|
|
1281
|
+
});
|
|
1282
|
+
let packageRootForMocks;
|
|
1283
|
+
if (target === "mock") {
|
|
1284
|
+
try {
|
|
1285
|
+
const { loadPackageManifest } = await import("./package-manifest-QH2RU64C.js");
|
|
1286
|
+
packageRootForMocks = (await loadPackageManifest(process.cwd())).root;
|
|
1287
|
+
} catch {
|
|
1288
|
+
packageRootForMocks = void 0;
|
|
1289
|
+
}
|
|
1290
|
+
}
|
|
1291
|
+
const result = local ? await (await import("./local-execute-SZV6XN4T.js")).runLocalExecute({
|
|
1292
|
+
code: args.code,
|
|
1293
|
+
...modulePath !== void 0 ? { modulePath } : {},
|
|
1294
|
+
params: args.params,
|
|
1295
|
+
conversationId: args.conversationId,
|
|
1296
|
+
...credentials !== void 0 ? { credentials } : {},
|
|
1297
|
+
token: mockToken ?? await resolveLocalExecuteBearer({
|
|
1298
|
+
tokenValues,
|
|
1299
|
+
mcpUrl,
|
|
1300
|
+
apiUrl,
|
|
1301
|
+
purpose: "execute --local",
|
|
1302
|
+
...org ? { org } : {}
|
|
1303
|
+
}),
|
|
1304
|
+
apiUrl,
|
|
1305
|
+
target,
|
|
1306
|
+
...org ? { org } : {},
|
|
1307
|
+
...mockDepResolve ? { depResolve: mockDepResolve } : {},
|
|
1308
|
+
...packageRootForMocks ? { packageRoot: packageRootForMocks } : {},
|
|
1309
|
+
...passthroughHosts.length > 0 ? { passthroughHosts } : {},
|
|
1310
|
+
allowPrivateNetwork: parsed.values["allow-private-network"] === true,
|
|
1311
|
+
onStatus: (message) => writeErr(`${message}
|
|
1312
|
+
`)
|
|
1313
|
+
}) : useToken ? await (await import("./remote-execute-QMQDVHOY.js")).runRemoteExecuteWithToken({
|
|
1314
|
+
code: typeof args.code === "string" ? args.code : void 0,
|
|
1315
|
+
invoke,
|
|
1316
|
+
params: args.params,
|
|
1317
|
+
conversationId: args.conversationId,
|
|
1318
|
+
...credentials !== void 0 ? { credentials } : {},
|
|
1319
|
+
token: requireApiToken(
|
|
1320
|
+
tokenValues,
|
|
1321
|
+
process.env,
|
|
1322
|
+
"execute with an API token",
|
|
1323
|
+
{ apiUrl }
|
|
1324
|
+
),
|
|
1325
|
+
apiUrl,
|
|
1326
|
+
...org ? { org } : {}
|
|
1327
|
+
}) : await (await import("./mcp-G2AWTIXR.js")).callKodyTool({
|
|
1328
|
+
name: "execute",
|
|
1329
|
+
args,
|
|
1330
|
+
mcpUrl,
|
|
1331
|
+
...org ? { org } : {}
|
|
1332
|
+
});
|
|
1333
|
+
write(formatToolResult(result, json));
|
|
1334
|
+
return result.isError ? 1 : 0;
|
|
1335
|
+
} finally {
|
|
1336
|
+
await closeMock?.();
|
|
1337
|
+
}
|
|
1338
|
+
}
|
|
1339
|
+
case "dev": {
|
|
1340
|
+
const { resolveTarget } = await import("./target-3QHY7JT4.js");
|
|
1341
|
+
const {
|
|
1342
|
+
parseDevPort,
|
|
1343
|
+
parseDevSubcommand,
|
|
1344
|
+
resolveDevAuth,
|
|
1345
|
+
runDevCheck,
|
|
1346
|
+
runDevEmit,
|
|
1347
|
+
runDevFetch,
|
|
1348
|
+
runDevJob,
|
|
1349
|
+
runDevServe,
|
|
1350
|
+
runDevWebhook,
|
|
1351
|
+
tryAttachedDevFetch
|
|
1352
|
+
} = await import("./dev-command-3LX234N6.js");
|
|
1353
|
+
const target = resolveTarget({
|
|
1354
|
+
command: "dev",
|
|
1355
|
+
flag: typeof parsed.values.target === "string" ? parsed.values.target : void 0
|
|
1356
|
+
});
|
|
1357
|
+
const { subcommand, rest } = parseDevSubcommand(parsed.positionals);
|
|
1358
|
+
const tokenValues = tokenFlagValues(parsed.values);
|
|
1359
|
+
const prodApiUrl = apiUrlFrom({
|
|
1360
|
+
apiUrl: typeof parsed.values["api-url"] === "string" ? parsed.values["api-url"] : void 0
|
|
1361
|
+
});
|
|
1362
|
+
const io = { stdout: write, stderr: writeErr };
|
|
1363
|
+
const bodyPath = typeof parsed.values.body === "string" ? parsed.values.body : void 0;
|
|
1364
|
+
if (subcommand === "check") {
|
|
1365
|
+
return await runDevCheck({ target, json, io });
|
|
1366
|
+
}
|
|
1367
|
+
const dryRun = parsed.values["dry-run"] === true;
|
|
1368
|
+
if (dryRun && subcommand !== "job" && subcommand !== "webhook" && subcommand !== "emit") {
|
|
1369
|
+
throw new Error(
|
|
1370
|
+
"`--dry-run` applies to `kody dev job|webhook|emit` only (shows the plan without invoking)."
|
|
1371
|
+
);
|
|
1372
|
+
}
|
|
1373
|
+
if (dryRun) {
|
|
1374
|
+
const dryAuth = { token: "dry-run", apiUrl: prodApiUrl };
|
|
1375
|
+
switch (subcommand) {
|
|
1376
|
+
case "job": {
|
|
1377
|
+
const jobName = rest[0];
|
|
1378
|
+
if (!jobName) throw new Error("Usage: kody dev job <name>");
|
|
1379
|
+
return await runDevJob({
|
|
1380
|
+
target,
|
|
1381
|
+
auth: dryAuth,
|
|
1382
|
+
jobName,
|
|
1383
|
+
json,
|
|
1384
|
+
dryRun: true,
|
|
1385
|
+
io
|
|
1386
|
+
});
|
|
1387
|
+
}
|
|
1388
|
+
case "webhook": {
|
|
1389
|
+
const webhookName = rest[0];
|
|
1390
|
+
if (!webhookName || !bodyPath) {
|
|
1391
|
+
throw new Error(
|
|
1392
|
+
"Usage: kody dev webhook <name> --body file.json"
|
|
1393
|
+
);
|
|
1394
|
+
}
|
|
1395
|
+
return await runDevWebhook({
|
|
1396
|
+
target,
|
|
1397
|
+
auth: dryAuth,
|
|
1398
|
+
webhookName,
|
|
1399
|
+
bodyPath,
|
|
1400
|
+
json,
|
|
1401
|
+
dryRun: true,
|
|
1402
|
+
io
|
|
1403
|
+
});
|
|
1404
|
+
}
|
|
1405
|
+
case "emit": {
|
|
1406
|
+
const event = rest[0];
|
|
1407
|
+
if (!event || !bodyPath) {
|
|
1408
|
+
throw new Error(
|
|
1409
|
+
"Usage: kody dev emit <event> --body event.json"
|
|
1410
|
+
);
|
|
1411
|
+
}
|
|
1412
|
+
return await runDevEmit({
|
|
1413
|
+
target,
|
|
1414
|
+
auth: dryAuth,
|
|
1415
|
+
event,
|
|
1416
|
+
bodyPath,
|
|
1417
|
+
json,
|
|
1418
|
+
dryRun: true,
|
|
1419
|
+
io
|
|
1420
|
+
});
|
|
1421
|
+
}
|
|
1422
|
+
default: {
|
|
1423
|
+
throw new Error(
|
|
1424
|
+
"`--dry-run` applies to `kody dev job|webhook|emit` only (shows the plan without invoking)."
|
|
1425
|
+
);
|
|
1426
|
+
}
|
|
1427
|
+
}
|
|
1428
|
+
}
|
|
1429
|
+
if (subcommand === "fetch" && parsed.values["no-attach"] !== true && rest[0]) {
|
|
1430
|
+
const attached = await tryAttachedDevFetch({
|
|
1431
|
+
target,
|
|
1432
|
+
path: rest[0],
|
|
1433
|
+
method: typeof parsed.values.method === "string" ? parsed.values.method : void 0,
|
|
1434
|
+
body: bodyPath ? await readFile(bodyPath, "utf8") : void 0,
|
|
1435
|
+
json,
|
|
1436
|
+
io
|
|
1437
|
+
});
|
|
1438
|
+
if (attached !== null) return attached;
|
|
1439
|
+
}
|
|
1440
|
+
const token = target === "prod" ? await resolveLocalExecuteBearer({
|
|
1441
|
+
tokenValues,
|
|
1442
|
+
mcpUrl,
|
|
1443
|
+
apiUrl: prodApiUrl,
|
|
1444
|
+
purpose: "kody dev",
|
|
1445
|
+
...org ? { org } : {}
|
|
1446
|
+
}) : "mock";
|
|
1447
|
+
const mockDepResolve = target === "mock" ? await (await import("./mock-dep-resolve-TVABDNR7.js")).tryResolveMockDepResolve({
|
|
1448
|
+
tokenValues,
|
|
1449
|
+
apiUrl: prodApiUrl,
|
|
1450
|
+
mcpUrl,
|
|
1451
|
+
...org ? { org } : {}
|
|
1452
|
+
}) : void 0;
|
|
1453
|
+
const { parsePassthroughHosts } = await import("./mock-fetch-gateway-B5TFGGQS.js");
|
|
1454
|
+
const passthroughHosts = parsePassthroughHosts(
|
|
1455
|
+
typeof parsed.values.passthrough === "string" ? parsed.values.passthrough : void 0
|
|
1456
|
+
);
|
|
1457
|
+
if (passthroughHosts.length > 0 && target !== "mock") {
|
|
1458
|
+
writeErr(
|
|
1459
|
+
"note: `--passthrough` is ignored on `--target prod` (outbound fetch mocking is mock-only).\n"
|
|
1460
|
+
);
|
|
1461
|
+
}
|
|
1462
|
+
const allowPrivateNetwork = parsed.values["allow-private-network"] === true;
|
|
1463
|
+
let packageId;
|
|
1464
|
+
try {
|
|
1465
|
+
const { loadPackageManifest } = await import("./package-manifest-QH2RU64C.js");
|
|
1466
|
+
const manifest = await loadPackageManifest(process.cwd());
|
|
1467
|
+
packageId = `local:${manifest.kodyId}`;
|
|
1468
|
+
} catch {
|
|
1469
|
+
packageId = void 0;
|
|
1470
|
+
}
|
|
1471
|
+
const auth = await resolveDevAuth({
|
|
1472
|
+
target,
|
|
1473
|
+
token,
|
|
1474
|
+
apiUrl: prodApiUrl,
|
|
1475
|
+
...org ? { org } : {},
|
|
1476
|
+
...mockDepResolve ? { depResolve: mockDepResolve } : {},
|
|
1477
|
+
...passthroughHosts.length > 0 && target === "mock" ? { passthroughHosts } : {},
|
|
1478
|
+
resetStorage: parsed.values["reset-storage"] === true,
|
|
1479
|
+
...packageId ? { packageId } : {},
|
|
1480
|
+
...org && target === "mock" ? { orgSlug: org } : {}
|
|
1481
|
+
});
|
|
1482
|
+
const port = typeof parsed.values.port === "string" ? parseDevPort(parsed.values.port) : void 0;
|
|
1483
|
+
const appBasePath = typeof parsed.values["app-base-path"] === "string" ? parsed.values["app-base-path"] : void 0;
|
|
1484
|
+
try {
|
|
1485
|
+
switch (subcommand) {
|
|
1486
|
+
case "serve":
|
|
1487
|
+
return await runDevServe({
|
|
1488
|
+
target,
|
|
1489
|
+
auth,
|
|
1490
|
+
port,
|
|
1491
|
+
appBasePath,
|
|
1492
|
+
allowPrivateNetwork,
|
|
1493
|
+
liveReload: parsed.values["no-live-reload"] !== true,
|
|
1494
|
+
json,
|
|
1495
|
+
...typeof parsed.values["ready-file"] === "string" ? { readyFile: parsed.values["ready-file"] } : {},
|
|
1496
|
+
io
|
|
1497
|
+
});
|
|
1498
|
+
case "fetch": {
|
|
1499
|
+
const path = rest[0];
|
|
1500
|
+
if (!path) {
|
|
1501
|
+
throw new Error(
|
|
1502
|
+
"Usage: kody dev fetch <path> [--method GET] [--body file.json]"
|
|
1503
|
+
);
|
|
1504
|
+
}
|
|
1505
|
+
let body;
|
|
1506
|
+
if (bodyPath) body = await readFile(bodyPath, "utf8");
|
|
1507
|
+
return await runDevFetch({
|
|
1508
|
+
target,
|
|
1509
|
+
auth,
|
|
1510
|
+
path,
|
|
1511
|
+
method: typeof parsed.values.method === "string" ? parsed.values.method : void 0,
|
|
1512
|
+
body,
|
|
1513
|
+
port,
|
|
1514
|
+
appBasePath,
|
|
1515
|
+
allowPrivateNetwork,
|
|
1516
|
+
json,
|
|
1517
|
+
io
|
|
1518
|
+
});
|
|
1519
|
+
}
|
|
1520
|
+
case "job": {
|
|
1521
|
+
const jobName = rest[0];
|
|
1522
|
+
if (!jobName) throw new Error("Usage: kody dev job <name>");
|
|
1523
|
+
return await runDevJob({
|
|
1524
|
+
target,
|
|
1525
|
+
auth,
|
|
1526
|
+
jobName,
|
|
1527
|
+
json,
|
|
1528
|
+
allowPrivateNetwork,
|
|
1529
|
+
io
|
|
1530
|
+
});
|
|
1531
|
+
}
|
|
1532
|
+
case "webhook": {
|
|
1533
|
+
const webhookName = rest[0];
|
|
1534
|
+
if (!webhookName || !bodyPath) {
|
|
1535
|
+
throw new Error(
|
|
1536
|
+
"Usage: kody dev webhook <name> --body file.json"
|
|
1537
|
+
);
|
|
1538
|
+
}
|
|
1539
|
+
return await runDevWebhook({
|
|
1540
|
+
target,
|
|
1541
|
+
auth,
|
|
1542
|
+
webhookName,
|
|
1543
|
+
bodyPath,
|
|
1544
|
+
json,
|
|
1545
|
+
allowPrivateNetwork,
|
|
1546
|
+
io
|
|
1547
|
+
});
|
|
1548
|
+
}
|
|
1549
|
+
case "emit": {
|
|
1550
|
+
const event = rest[0];
|
|
1551
|
+
if (!event || !bodyPath) {
|
|
1552
|
+
throw new Error(
|
|
1553
|
+
"Usage: kody dev emit <event> --body event.json"
|
|
1554
|
+
);
|
|
1555
|
+
}
|
|
1556
|
+
return await runDevEmit({
|
|
1557
|
+
target,
|
|
1558
|
+
auth,
|
|
1559
|
+
event,
|
|
1560
|
+
bodyPath,
|
|
1561
|
+
json,
|
|
1562
|
+
allowPrivateNetwork,
|
|
1563
|
+
io
|
|
1564
|
+
});
|
|
1565
|
+
}
|
|
1566
|
+
default: {
|
|
1567
|
+
const exhaustive = subcommand;
|
|
1568
|
+
throw new Error(
|
|
1569
|
+
`Unhandled kody dev subcommand: ${String(exhaustive)}`
|
|
1570
|
+
);
|
|
1571
|
+
}
|
|
1572
|
+
}
|
|
1573
|
+
} catch (error) {
|
|
1574
|
+
await auth.closeMock?.();
|
|
1575
|
+
throw error;
|
|
1576
|
+
}
|
|
1577
|
+
}
|
|
1578
|
+
case "api": {
|
|
1579
|
+
const operationId = parsed.positionals[0]?.trim() ?? "";
|
|
1580
|
+
if (!operationId || parsed.positionals.length > 1) {
|
|
1581
|
+
throw new Error(
|
|
1582
|
+
"Usage: kody api <operationId> [--params <json>] [--token <token>] [--api-url <url>] [--json]"
|
|
1583
|
+
);
|
|
1584
|
+
}
|
|
1585
|
+
const apiUrl = apiUrlFrom({
|
|
1586
|
+
apiUrl: typeof parsed.values["api-url"] === "string" ? parsed.values["api-url"] : void 0
|
|
1587
|
+
});
|
|
1588
|
+
const tokenValues = tokenFlagValues(parsed.values);
|
|
1589
|
+
const params = parseApiParamsJson(
|
|
1590
|
+
typeof parsed.values.params === "string" ? parsed.values.params : void 0
|
|
1591
|
+
);
|
|
1592
|
+
const { callOpenApiOperation } = await import("./open-api-client-DVVMLY7P.js");
|
|
1593
|
+
const result = await callOpenApiOperation({
|
|
1594
|
+
operationId,
|
|
1595
|
+
params,
|
|
1596
|
+
token: requireApiToken(tokenValues, process.env, "api", { apiUrl }),
|
|
1597
|
+
apiUrl,
|
|
1598
|
+
...org ? { org } : {}
|
|
1599
|
+
});
|
|
1600
|
+
write(`${JSON.stringify(result, null, 2)}
|
|
1601
|
+
`);
|
|
1602
|
+
return 0;
|
|
1603
|
+
}
|
|
1604
|
+
case "package": {
|
|
1605
|
+
const action = parsed.positionals[0];
|
|
1606
|
+
const apiUrl = apiUrlFrom({
|
|
1607
|
+
apiUrl: typeof parsed.values["api-url"] === "string" ? parsed.values["api-url"] : void 0
|
|
1608
|
+
});
|
|
1609
|
+
const tokenValues = tokenFlagValues(parsed.values);
|
|
1610
|
+
if (isPackageCollaboratorAction(action)) {
|
|
1611
|
+
const plan = parsePackageCollaboratorCommand({
|
|
1612
|
+
action,
|
|
1613
|
+
positionals: parsed.positionals.slice(1),
|
|
1614
|
+
values: parsed.values
|
|
1615
|
+
});
|
|
1616
|
+
const token = requireApiToken(tokenValues, process.env, `package ${action}`, {
|
|
1617
|
+
apiUrl
|
|
1618
|
+
});
|
|
1619
|
+
const { callOpenApiOperation: callOpenApiOperation2 } = await import("./open-api-client-DVVMLY7P.js");
|
|
1620
|
+
write(
|
|
1621
|
+
await runPackageCollaboratorPlan({
|
|
1622
|
+
plan,
|
|
1623
|
+
json,
|
|
1624
|
+
call: (operationId, params2) => callOpenApiOperation2({
|
|
1625
|
+
operationId,
|
|
1626
|
+
params: params2,
|
|
1627
|
+
token,
|
|
1628
|
+
apiUrl,
|
|
1629
|
+
...org ? { org } : {}
|
|
1630
|
+
})
|
|
1631
|
+
})
|
|
1632
|
+
);
|
|
1633
|
+
return 0;
|
|
1634
|
+
}
|
|
1635
|
+
if (action !== "publish") {
|
|
1636
|
+
throw new Error(
|
|
1637
|
+
`Usage: kody package publish [<@owner/leaf|package_id>] [--params <json>] [--token <token>] [--api-url <url>] [--org <slug>]
|
|
1638
|
+
${packageCollaboratorUsage}`
|
|
1639
|
+
);
|
|
1640
|
+
}
|
|
1641
|
+
const params = packagePublishParams({
|
|
1642
|
+
positional: parsed.positionals[1],
|
|
1643
|
+
paramsJson: typeof parsed.values.params === "string" ? parsed.values.params : void 0
|
|
1644
|
+
});
|
|
1645
|
+
const { callOpenApiOperation } = await import("./open-api-client-DVVMLY7P.js");
|
|
1646
|
+
const publishToken = requireApiToken(tokenValues, process.env, "package publish", {
|
|
1647
|
+
apiUrl
|
|
1648
|
+
});
|
|
1649
|
+
const call = (operationId, operationParams) => callOpenApiOperation({
|
|
1650
|
+
operationId,
|
|
1651
|
+
params: operationParams,
|
|
1652
|
+
token: publishToken,
|
|
1653
|
+
apiUrl,
|
|
1654
|
+
...org ? { org } : {}
|
|
1655
|
+
});
|
|
1656
|
+
const result = await call(
|
|
1657
|
+
"packagePublishExternalPush",
|
|
1658
|
+
await resolvePackagePublishTarget(params, call)
|
|
1659
|
+
);
|
|
1660
|
+
write(`${JSON.stringify(result, null, 2)}
|
|
1661
|
+
`);
|
|
1662
|
+
return 0;
|
|
1663
|
+
}
|
|
1664
|
+
case "install": {
|
|
1665
|
+
const { runInstall } = await import("./install-ZML2TCDG.js");
|
|
1666
|
+
const result = await runInstall(
|
|
1667
|
+
{
|
|
1668
|
+
mcpUrl,
|
|
1669
|
+
clients: typeof parsed.values.clients === "string" ? parsed.values.clients : void 0,
|
|
1670
|
+
yes: parsed.values.yes === true,
|
|
1671
|
+
project: parsed.values.project === true,
|
|
1672
|
+
json
|
|
1673
|
+
},
|
|
1674
|
+
{ stdout: write }
|
|
1675
|
+
);
|
|
1676
|
+
return result.code;
|
|
1677
|
+
}
|
|
1678
|
+
case "skill": {
|
|
1679
|
+
const action = parsed.positionals[0] ?? "install";
|
|
1680
|
+
if (action !== "install") {
|
|
1681
|
+
throw new Error("Usage: kody skill install [--project]");
|
|
1682
|
+
}
|
|
1683
|
+
const { installSkill } = await import("./skill-ENPATRIW.js");
|
|
1684
|
+
const targets = await installSkill({ project: parsed.values.project === true });
|
|
1685
|
+
write(
|
|
1686
|
+
`Installed the Kody skill to:
|
|
1687
|
+
${targets.map((target) => `- ${target.host}: ${target.path}`).join("\n")}
|
|
1688
|
+
`
|
|
1689
|
+
);
|
|
1690
|
+
return 0;
|
|
1691
|
+
}
|
|
1692
|
+
default: {
|
|
1693
|
+
const exhaustive = parsed.command;
|
|
1694
|
+
throw new Error(`Unhandled command: ${String(exhaustive)}`);
|
|
1695
|
+
}
|
|
1696
|
+
}
|
|
1697
|
+
}
|
|
1698
|
+
async function readStdin() {
|
|
1699
|
+
const chunks = [];
|
|
1700
|
+
for await (const chunk of process.stdin) {
|
|
1701
|
+
chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
|
|
1702
|
+
}
|
|
1703
|
+
return Buffer.concat(chunks).toString("utf8");
|
|
1704
|
+
}
|
|
1705
|
+
async function tryResolveLocalPackageInvoke(invoke) {
|
|
1706
|
+
const trimmed = invoke.trim();
|
|
1707
|
+
if (!trimmed) return null;
|
|
1708
|
+
if (isPublishedPackageInvokeSpecifier(trimmed)) return null;
|
|
1709
|
+
const { loadPackageManifest, resolveExportModulePath } = await import("./package-manifest-QH2RU64C.js");
|
|
1710
|
+
const { StructuredCliError } = await import("./structured-error-C65GQ53Z.js");
|
|
1711
|
+
let manifest;
|
|
1712
|
+
try {
|
|
1713
|
+
manifest = await loadPackageManifest(process.cwd());
|
|
1714
|
+
} catch {
|
|
1715
|
+
return null;
|
|
1716
|
+
}
|
|
1717
|
+
try {
|
|
1718
|
+
const modulePath = resolveExportModulePath(manifest, trimmed, {
|
|
1719
|
+
exportsOnly: true
|
|
1720
|
+
});
|
|
1721
|
+
const { access } = await import("node:fs/promises");
|
|
1722
|
+
try {
|
|
1723
|
+
await access(modulePath);
|
|
1724
|
+
} catch {
|
|
1725
|
+
throw new StructuredCliError({
|
|
1726
|
+
code: "dev_surface_missing",
|
|
1727
|
+
message: `No package export ${JSON.stringify(trimmed)} (path missing: ${modulePath}).`,
|
|
1728
|
+
where: manifest.packageJsonPath,
|
|
1729
|
+
fix: `Known exports: ${Object.keys(manifest.exports).join(", ") || "(none)"}.`
|
|
1730
|
+
});
|
|
1731
|
+
}
|
|
1732
|
+
return { modulePath, kodyId: manifest.kodyId, packageRoot: manifest.root };
|
|
1733
|
+
} catch (error) {
|
|
1734
|
+
if (error instanceof StructuredCliError) throw error;
|
|
1735
|
+
return null;
|
|
1736
|
+
}
|
|
1737
|
+
}
|
|
1738
|
+
function executeSourcesConflict(input) {
|
|
1739
|
+
return input.invoke !== void 0 && (input.hasCodeFlag || input.hasFileFlag || input.positionalModule.length > 0);
|
|
1740
|
+
}
|
|
1741
|
+
function buildExecuteToolArgs(input) {
|
|
1742
|
+
const invoke = input.invoke;
|
|
1743
|
+
const code = input.code;
|
|
1744
|
+
if (invoke !== void 0 && code !== void 0 && code.length > 0) {
|
|
1745
|
+
throw new Error("--invoke cannot be combined with --code, --file, or a module string.");
|
|
1746
|
+
}
|
|
1747
|
+
if (invoke !== void 0) {
|
|
1748
|
+
if (!invoke) {
|
|
1749
|
+
throw new Error("Provide a non-empty --invoke value.");
|
|
1750
|
+
}
|
|
1751
|
+
return attachExecuteCommonArgs({ invoke }, input);
|
|
1752
|
+
}
|
|
1753
|
+
if (code) {
|
|
1754
|
+
return attachExecuteCommonArgs({ code }, input);
|
|
1755
|
+
}
|
|
1756
|
+
throw new Error("Provide --invoke, --code, --file, or a module string.");
|
|
1757
|
+
}
|
|
1758
|
+
function attachExecuteCommonArgs(args, input) {
|
|
1759
|
+
if (input.paramsJson !== void 0) {
|
|
1760
|
+
args.params = JSON.parse(input.paramsJson);
|
|
1761
|
+
}
|
|
1762
|
+
if (input.conversationId !== void 0) {
|
|
1763
|
+
args.conversationId = input.conversationId;
|
|
1764
|
+
}
|
|
1765
|
+
if (input.credentials !== void 0) {
|
|
1766
|
+
args.credentials = input.credentials;
|
|
1767
|
+
}
|
|
1768
|
+
return args;
|
|
1769
|
+
}
|
|
1770
|
+
async function runAuthSetupGit(input) {
|
|
1771
|
+
const { authSetupGit, setupGitDefaultScopes } = await import("./setup-git-5KCUBYPB.js");
|
|
1772
|
+
const apiUrl = apiUrlFrom({
|
|
1773
|
+
apiUrl: typeof input.values["api-url"] === "string" ? input.values["api-url"] : void 0
|
|
1774
|
+
});
|
|
1775
|
+
const scopes = parseCliScopesFlag(
|
|
1776
|
+
typeof input.values.scopes === "string" ? input.values.scopes : void 0
|
|
1777
|
+
);
|
|
1778
|
+
const lifetime = resolveCliTokenLifetime({
|
|
1779
|
+
lifetime: typeof input.values.lifetime === "string" ? input.values.lifetime : "long",
|
|
1780
|
+
idleTtlSeconds: parseCliLifetimeSecondsFlag(
|
|
1781
|
+
typeof input.values["idle-ttl-seconds"] === "string" ? input.values["idle-ttl-seconds"] : void 0,
|
|
1782
|
+
"--idle-ttl-seconds"
|
|
1783
|
+
),
|
|
1784
|
+
maxLifetimeSeconds: parseCliLifetimeSecondsFlag(
|
|
1785
|
+
typeof input.values["max-lifetime-seconds"] === "string" ? input.values["max-lifetime-seconds"] : void 0,
|
|
1786
|
+
"--max-lifetime-seconds"
|
|
1787
|
+
)
|
|
1788
|
+
});
|
|
1789
|
+
const tokenValues = tokenFlagValues(input.values);
|
|
1790
|
+
const mintScopes = scopes ?? setupGitDefaultScopes;
|
|
1791
|
+
const hasLoginSession = loadCredentials(input.mcpUrl, void 0, void 0, {
|
|
1792
|
+
org: input.org
|
|
1793
|
+
}) != null;
|
|
1794
|
+
const result = await authSetupGit({
|
|
1795
|
+
apiUrl,
|
|
1796
|
+
mcpUrl: input.mcpUrl,
|
|
1797
|
+
token: tokenValues.token,
|
|
1798
|
+
hasLoginSession,
|
|
1799
|
+
...scopes ? { scopesOverride: scopes } : {},
|
|
1800
|
+
lifetime,
|
|
1801
|
+
mint: bootstrapMinter({
|
|
1802
|
+
scopes: mintScopes,
|
|
1803
|
+
lifetime,
|
|
1804
|
+
mcpUrl: input.mcpUrl,
|
|
1805
|
+
apiUrl,
|
|
1806
|
+
tokenValues,
|
|
1807
|
+
...input.org ? { org: input.org } : {}
|
|
1808
|
+
})
|
|
1809
|
+
});
|
|
1810
|
+
input.write(
|
|
1811
|
+
[
|
|
1812
|
+
`Git HTTPS credential helper installed for https://${result.host}/`,
|
|
1813
|
+
`helper: ${result.helperCommand}`,
|
|
1814
|
+
`token: ${result.minted ? "minted" : "reused"} ${result.tokenId} (org_binding=user)`,
|
|
1815
|
+
`scopes: ${result.scopes.join(", ") || "(none)"}`,
|
|
1816
|
+
`expires: ${result.expiresAt ?? "unknown"}`,
|
|
1817
|
+
result.backendKind === "file" && result.backendPath ? `OS keychain was unavailable; token saved at ${result.backendPath} (mode 0600).` : result.minted ? "Token stored in the OS keychain (or existing store)." : "Using the existing stored API token.",
|
|
1818
|
+
"",
|
|
1819
|
+
"This user-owned token authorizes every @owner/name.git you can access (all orgs).",
|
|
1820
|
+
"Try: git clone https://kody.codes/@owner/name.git",
|
|
1821
|
+
"Undo later: kody auth remove-git",
|
|
1822
|
+
""
|
|
1823
|
+
].join("\n")
|
|
1824
|
+
);
|
|
1825
|
+
return 0;
|
|
1826
|
+
}
|
|
1827
|
+
async function runAuthRemoveGit(input) {
|
|
1828
|
+
const { authRemoveGit, formatAuthRemoveGitReport } = await import("./setup-git-5KCUBYPB.js");
|
|
1829
|
+
const apiUrl = apiUrlFrom({
|
|
1830
|
+
apiUrl: typeof input.values["api-url"] === "string" ? input.values["api-url"] : void 0
|
|
1831
|
+
});
|
|
1832
|
+
const result = await authRemoveGit({
|
|
1833
|
+
apiUrl,
|
|
1834
|
+
mcpUrl: input.mcpUrl
|
|
1835
|
+
});
|
|
1836
|
+
input.write(formatAuthRemoveGitReport(result));
|
|
1837
|
+
return 0;
|
|
1838
|
+
}
|
|
1839
|
+
function bootstrapMinter(input) {
|
|
1840
|
+
return async (params) => {
|
|
1841
|
+
if (shouldUseApiToken({
|
|
1842
|
+
tokenValues: input.tokenValues,
|
|
1843
|
+
mcpUrl: input.mcpUrl,
|
|
1844
|
+
apiUrl: input.apiUrl,
|
|
1845
|
+
allowEnvWithoutLogin: true,
|
|
1846
|
+
...input.org ? { org: input.org } : {}
|
|
1847
|
+
})) {
|
|
1848
|
+
const token = requireApiToken(input.tokenValues, process.env, "auth bootstrap --scopes", {
|
|
1849
|
+
apiUrl: input.apiUrl
|
|
1850
|
+
});
|
|
1851
|
+
const { callOpenApiOperation } = await import("./open-api-client-DVVMLY7P.js");
|
|
1852
|
+
try {
|
|
1853
|
+
return await callOpenApiOperation({
|
|
1854
|
+
token,
|
|
1855
|
+
apiUrl: input.apiUrl,
|
|
1856
|
+
operationId: cliCredentialBootstrapOperationId,
|
|
1857
|
+
params,
|
|
1858
|
+
...input.org ? { org: input.org } : {}
|
|
1859
|
+
});
|
|
1860
|
+
} catch (error) {
|
|
1861
|
+
if (error instanceof Error && /cannot grant scopes it does not hold/i.test(error.message)) {
|
|
1862
|
+
throw new Error(
|
|
1863
|
+
`${error.message} A token can only mint scopes it already holds. Run \`kody login\` and retry without --token (a login session can mint any scope your org role grants), or from Kody MCP call \`${cliBootstrapMintCall(input.scopes, bootstrapMintLifetimeFields(input.lifetime))}\` and run the returned cli_command.`
|
|
1864
|
+
);
|
|
1865
|
+
}
|
|
1866
|
+
throw error;
|
|
1867
|
+
}
|
|
1868
|
+
}
|
|
1869
|
+
if (loadCredentials(input.mcpUrl, void 0, void 0, {
|
|
1870
|
+
org: input.org
|
|
1871
|
+
})) {
|
|
1872
|
+
return (await import("./mcp-G2AWTIXR.js")).callKodyApiOperation({
|
|
1873
|
+
operationId: cliCredentialBootstrapOperationId,
|
|
1874
|
+
params,
|
|
1875
|
+
mcpUrl: input.mcpUrl,
|
|
1876
|
+
...input.org ? { org: input.org } : {}
|
|
1877
|
+
});
|
|
1878
|
+
}
|
|
1879
|
+
throw new Error(
|
|
1880
|
+
`auth bootstrap --scopes mints with your current Kody credential, and none was found. Run \`kody login\` and retry, or from Kody MCP call \`${cliBootstrapMintCall(input.scopes, bootstrapMintLifetimeFields(input.lifetime))}\` and run the returned cli_command.`
|
|
1881
|
+
);
|
|
1882
|
+
};
|
|
1883
|
+
}
|
|
1884
|
+
function tokenFlagValues(values) {
|
|
1885
|
+
return {
|
|
1886
|
+
token: typeof values.token === "string" ? values.token : void 0
|
|
1887
|
+
};
|
|
1888
|
+
}
|
|
1889
|
+
function parseApiParamsJson(paramsJson) {
|
|
1890
|
+
if (paramsJson === void 0) return {};
|
|
1891
|
+
let parsed;
|
|
1892
|
+
try {
|
|
1893
|
+
parsed = JSON.parse(paramsJson);
|
|
1894
|
+
} catch {
|
|
1895
|
+
throw new Error("--params must be valid JSON (a flat object).");
|
|
1896
|
+
}
|
|
1897
|
+
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
1898
|
+
throw new Error(`--params must be a JSON object (e.g. '{"query":"email"}').`);
|
|
1899
|
+
}
|
|
1900
|
+
return parsed;
|
|
1901
|
+
}
|
|
1902
|
+
var packageIdUuidPattern = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
1903
|
+
function packagePublishParams(input) {
|
|
1904
|
+
const params = parseApiParamsJson(input.paramsJson);
|
|
1905
|
+
const ref = input.positional?.trim();
|
|
1906
|
+
if (!ref) return params;
|
|
1907
|
+
if (packageIdUuidPattern.test(ref)) {
|
|
1908
|
+
if (params.package_id === void 0) params.package_id = ref;
|
|
1909
|
+
} else if (params.kody_id === void 0) {
|
|
1910
|
+
params.kody_id = ref;
|
|
1911
|
+
}
|
|
1912
|
+
return params;
|
|
1913
|
+
}
|
|
1914
|
+
async function resolvePackagePublishTarget(params, call) {
|
|
1915
|
+
if (params.package_id !== void 0 || typeof params.kody_id !== "string") return params;
|
|
1916
|
+
const ref = params.kody_id.trim();
|
|
1917
|
+
const listed = await call("packageList", {});
|
|
1918
|
+
const packages = listed.packages ?? [];
|
|
1919
|
+
const leaf = ref.includes("/") ? ref.slice(ref.lastIndexOf("/") + 1) : ref;
|
|
1920
|
+
const byName = packages.filter((pkg) => pkg.name === ref);
|
|
1921
|
+
const matches = byName.length > 0 ? byName : ref.startsWith("@") ? [] : packages.filter((pkg) => pkg.kody_id === leaf);
|
|
1922
|
+
if (matches.length !== 1) {
|
|
1923
|
+
const known = packages.map((pkg) => pkg.name).slice(0, 20).join(", ");
|
|
1924
|
+
throw new Error(
|
|
1925
|
+
matches.length === 0 ? `No saved package named "${ref}" in this org.${known ? ` Saved packages: ${known}.` : ""} Pass the scoped name (@owner/leaf), the package_id, or --org <slug> for another org.` : `"${ref}" matches several saved packages (${matches.map((pkg) => `${pkg.name} = ${pkg.package_id}`).join(", ")}). Pass the scoped name or the package_id.`
|
|
1926
|
+
);
|
|
1927
|
+
}
|
|
1928
|
+
const { kody_id: _name, ...rest } = params;
|
|
1929
|
+
return { ...rest, package_id: matches[0].package_id };
|
|
1930
|
+
}
|
|
1931
|
+
function shouldUseApiToken(input) {
|
|
1932
|
+
if (hasExplicitTokenFlag(input.tokenValues)) return true;
|
|
1933
|
+
if (!input.allowEnvWithoutLogin) return false;
|
|
1934
|
+
if (!resolveScopedApiToken({
|
|
1935
|
+
tokenValues: input.tokenValues,
|
|
1936
|
+
env: input.env,
|
|
1937
|
+
apiUrl: input.apiUrl,
|
|
1938
|
+
loadApiToken: input.loadApiToken
|
|
1939
|
+
})) {
|
|
1940
|
+
return false;
|
|
1941
|
+
}
|
|
1942
|
+
const loggedIn = input.hasSession ?? loadCredentials(input.mcpUrl, void 0, void 0, {
|
|
1943
|
+
org: input.org
|
|
1944
|
+
}) != null;
|
|
1945
|
+
return !loggedIn;
|
|
1946
|
+
}
|
|
1947
|
+
|
|
1948
|
+
export {
|
|
1949
|
+
apiUrlFrom,
|
|
1950
|
+
resolveCommand,
|
|
1951
|
+
runCli,
|
|
1952
|
+
executeSourcesConflict,
|
|
1953
|
+
buildExecuteToolArgs,
|
|
1954
|
+
parseApiParamsJson,
|
|
1955
|
+
packagePublishParams,
|
|
1956
|
+
resolvePackagePublishTarget,
|
|
1957
|
+
shouldUseApiToken
|
|
1958
|
+
};
|
|
1959
|
+
//# sourceMappingURL=chunk-TIL35OWA.js.map
|