@proagentstore/cli 0.4.38 → 0.4.39
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.
|
@@ -19,11 +19,35 @@ import { join } from "node:path";
|
|
|
19
19
|
export function sanitizeSessionName(label) {
|
|
20
20
|
return label.replace(/[^a-zA-Z0-9_-]/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "").slice(0, 60) || "session";
|
|
21
21
|
}
|
|
22
|
+
/**
|
|
23
|
+
* The clone URL with the credential embedded, or the URL untouched.
|
|
24
|
+
*
|
|
25
|
+
* PURE and exported so the one line that decides where a credential goes is unit-testable
|
|
26
|
+
* without a network or a git binary. `username` is provider-specific — GitHub wants
|
|
27
|
+
* `x-access-token`, GitLab `oauth2`, Bitbucket `x-token-auth` (#221) — and it defaults to the
|
|
28
|
+
* value this function used to hardcode, so a cloud that sends only `token` behaves as before.
|
|
29
|
+
*
|
|
30
|
+
* Only https carries a credential: git ignores userinfo on an ssh URL, so injecting there would
|
|
31
|
+
* be pure exposure for no effect. Both halves are percent-encoded — a secret containing `@`,
|
|
32
|
+
* `/` or `:` would otherwise re-parse the URL into a DIFFERENT host and send the credential
|
|
33
|
+
* there. GitHub's tokens contain none of those, so nothing changes for the existing provider.
|
|
34
|
+
*/
|
|
35
|
+
export function authenticatedCloneUrl(cloneUrl, token, username) {
|
|
36
|
+
if (!token || !/^https:\/\//i.test(cloneUrl))
|
|
37
|
+
return cloneUrl;
|
|
38
|
+
const user = encodeURIComponent(username || "x-access-token");
|
|
39
|
+
return cloneUrl.replace(/^https:\/\//i, `https://${user}:${encodeURIComponent(token)}@`);
|
|
40
|
+
}
|
|
22
41
|
/**
|
|
23
42
|
* Ensure a repo is present at `dir`, cloning it from `cloneUrl` if not. Idempotent
|
|
24
|
-
* — an existing checkout is left alone (no clobber). For private repos
|
|
25
|
-
*
|
|
26
|
-
*
|
|
43
|
+
* — an existing checkout is left alone (no clobber). For private repos the cloud
|
|
44
|
+
* sends a token, injected as the password half of an https URL. The coding CLI then
|
|
45
|
+
* runs in this directory.
|
|
46
|
+
*
|
|
47
|
+
* `tokenUsername` is the USERNAME half, and it is provider-specific: GitHub wants
|
|
48
|
+
* `x-access-token`, GitLab `oauth2`, Bitbucket `x-token-auth` (#221). It defaults to
|
|
49
|
+
* `x-access-token` — the value this function used to hardcode — so an older cloud that
|
|
50
|
+
* sends only `token` behaves exactly as before.
|
|
27
51
|
*
|
|
28
52
|
* Returns the absolute working directory. Throws on clone failure so the caller
|
|
29
53
|
* can surface it (a session can't start without its repo).
|
|
@@ -50,10 +74,7 @@ export function ensureRepo(dir, opts = {}) {
|
|
|
50
74
|
}
|
|
51
75
|
rmSync(dir, { recursive: true, force: true });
|
|
52
76
|
}
|
|
53
|
-
|
|
54
|
-
if (opts.token && /^https:\/\//.test(url)) {
|
|
55
|
-
url = url.replace(/^https:\/\//, `https://x-access-token:${opts.token}@`);
|
|
56
|
-
}
|
|
77
|
+
const url = authenticatedCloneUrl(opts.cloneUrl, opts.token, opts.tokenUsername);
|
|
57
78
|
const args = ["clone", "--depth", "1"];
|
|
58
79
|
if (opts.branch)
|
|
59
80
|
args.push("--branch", opts.branch);
|
|
@@ -71,7 +71,7 @@ export class CodingRuntime {
|
|
|
71
71
|
const workDir = input.workDir
|
|
72
72
|
? resolve(input.workDir.replace(/^~(?=$|\/)/, homedir()))
|
|
73
73
|
: join(this.reposBaseDir, sanitizeSessionName(input.repoId));
|
|
74
|
-
ensureRepo(workDir, { cloneUrl: input.cloneUrl, branch: input.branch, token: input.token });
|
|
74
|
+
ensureRepo(workDir, { cloneUrl: input.cloneUrl, branch: input.branch, token: input.token, tokenUsername: input.tokenUsername });
|
|
75
75
|
session = new HeadlessSession({
|
|
76
76
|
id: input.sessionId,
|
|
77
77
|
workDir,
|