git-workspace-service 0.3.0 → 0.3.1
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/index.cjs +97 -21
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +8 -2
- package/dist/index.d.ts +8 -2
- package/dist/index.js +97 -21
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -324,24 +324,28 @@ var WorkspaceService = class {
|
|
|
324
324
|
credential = parent.credential;
|
|
325
325
|
} else {
|
|
326
326
|
await fs3__namespace.mkdir(workspacePath, { recursive: true });
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
327
|
+
if (config.userCredentials) {
|
|
328
|
+
credential = await this.credentialService.getCredentials({
|
|
329
|
+
repo: config.repo,
|
|
330
|
+
access: "write",
|
|
331
|
+
context: {
|
|
332
|
+
executionId: config.execution.id,
|
|
333
|
+
taskId: config.task.id,
|
|
334
|
+
userId: config.user?.id,
|
|
335
|
+
reason: `Workspace for ${config.task.role} in ${config.execution.patternName}`
|
|
336
|
+
},
|
|
337
|
+
userProvided: config.userCredentials
|
|
338
|
+
});
|
|
339
|
+
}
|
|
340
|
+
if (credential) {
|
|
341
|
+
await this.emitEvent({
|
|
342
|
+
type: "credential:granted",
|
|
343
|
+
workspaceId,
|
|
344
|
+
credentialId: credential.id,
|
|
331
345
|
executionId: config.execution.id,
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
},
|
|
336
|
-
userProvided: config.userCredentials
|
|
337
|
-
});
|
|
338
|
-
await this.emitEvent({
|
|
339
|
-
type: "credential:granted",
|
|
340
|
-
workspaceId,
|
|
341
|
-
credentialId: credential.id,
|
|
342
|
-
executionId: config.execution.id,
|
|
343
|
-
timestamp: /* @__PURE__ */ new Date()
|
|
344
|
-
});
|
|
346
|
+
timestamp: /* @__PURE__ */ new Date()
|
|
347
|
+
});
|
|
348
|
+
}
|
|
345
349
|
}
|
|
346
350
|
const branchInfo = createBranchInfo(
|
|
347
351
|
{
|
|
@@ -358,6 +362,7 @@ var WorkspaceService = class {
|
|
|
358
362
|
repo: config.repo,
|
|
359
363
|
branch: branchInfo,
|
|
360
364
|
credential,
|
|
365
|
+
// Will be set before any write operations
|
|
361
366
|
provisionedAt: /* @__PURE__ */ new Date(),
|
|
362
367
|
status: "provisioning",
|
|
363
368
|
strategy,
|
|
@@ -373,7 +378,38 @@ var WorkspaceService = class {
|
|
|
373
378
|
try {
|
|
374
379
|
if (strategy === "clone") {
|
|
375
380
|
this.updateProgress(workspace, "cloning", "Cloning repository");
|
|
376
|
-
|
|
381
|
+
if (!credential) {
|
|
382
|
+
const cloneResult = await this.tryUnauthenticatedClone(workspace);
|
|
383
|
+
if (!cloneResult.success) {
|
|
384
|
+
this.log(
|
|
385
|
+
"info",
|
|
386
|
+
{ workspaceId, error: cloneResult.error },
|
|
387
|
+
"Unauthenticated clone failed, requesting credentials"
|
|
388
|
+
);
|
|
389
|
+
credential = await this.credentialService.getCredentials({
|
|
390
|
+
repo: config.repo,
|
|
391
|
+
access: "write",
|
|
392
|
+
context: {
|
|
393
|
+
executionId: config.execution.id,
|
|
394
|
+
taskId: config.task.id,
|
|
395
|
+
userId: config.user?.id,
|
|
396
|
+
reason: `Workspace for ${config.task.role} in ${config.execution.patternName}`
|
|
397
|
+
}
|
|
398
|
+
});
|
|
399
|
+
workspace.credential = credential;
|
|
400
|
+
this.workspaces.set(workspaceId, workspace);
|
|
401
|
+
await this.emitEvent({
|
|
402
|
+
type: "credential:granted",
|
|
403
|
+
workspaceId,
|
|
404
|
+
credentialId: credential.id,
|
|
405
|
+
executionId: config.execution.id,
|
|
406
|
+
timestamp: /* @__PURE__ */ new Date()
|
|
407
|
+
});
|
|
408
|
+
await this.cloneRepo(workspace, credential.token);
|
|
409
|
+
}
|
|
410
|
+
} else {
|
|
411
|
+
await this.cloneRepo(workspace, credential.token);
|
|
412
|
+
}
|
|
377
413
|
this.updateProgress(workspace, "creating_branch", "Creating branch");
|
|
378
414
|
await this.createBranch(workspace);
|
|
379
415
|
} else {
|
|
@@ -594,7 +630,7 @@ var WorkspaceService = class {
|
|
|
594
630
|
});
|
|
595
631
|
}
|
|
596
632
|
}
|
|
597
|
-
if (workspace.strategy === "clone") {
|
|
633
|
+
if (workspace.strategy === "clone" && workspace.credential) {
|
|
598
634
|
await this.credentialService.revokeCredential(workspace.credential.id);
|
|
599
635
|
await this.emitEvent({
|
|
600
636
|
type: "credential:revoked",
|
|
@@ -630,6 +666,36 @@ var WorkspaceService = class {
|
|
|
630
666
|
// ─────────────────────────────────────────────────────────────
|
|
631
667
|
// Private Methods
|
|
632
668
|
// ─────────────────────────────────────────────────────────────
|
|
669
|
+
/**
|
|
670
|
+
* Try to clone a public repository without authentication
|
|
671
|
+
*/
|
|
672
|
+
async tryUnauthenticatedClone(workspace) {
|
|
673
|
+
let cloneUrl = workspace.repo;
|
|
674
|
+
if (cloneUrl.startsWith("git@github.com:")) {
|
|
675
|
+
cloneUrl = cloneUrl.replace("git@github.com:", "https://github.com/");
|
|
676
|
+
}
|
|
677
|
+
if (!cloneUrl.endsWith(".git")) {
|
|
678
|
+
cloneUrl = `${cloneUrl}.git`;
|
|
679
|
+
}
|
|
680
|
+
if (!cloneUrl.startsWith("https://")) {
|
|
681
|
+
cloneUrl = `https://${cloneUrl}`;
|
|
682
|
+
}
|
|
683
|
+
try {
|
|
684
|
+
await this.execInDir(
|
|
685
|
+
workspace.path,
|
|
686
|
+
`git clone --depth 1 --branch ${workspace.branch.baseBranch} ${cloneUrl} .`
|
|
687
|
+
);
|
|
688
|
+
this.log("info", { workspaceId: workspace.id }, "Public repository cloned without authentication");
|
|
689
|
+
return { success: true };
|
|
690
|
+
} catch (error) {
|
|
691
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
692
|
+
const isAuthError = errorMessage.includes("401") || errorMessage.includes("403") || errorMessage.includes("Authentication failed") || errorMessage.includes("could not read Username") || errorMessage.includes("terminal prompts disabled");
|
|
693
|
+
if (isAuthError) {
|
|
694
|
+
return { success: false, error: "Authentication required" };
|
|
695
|
+
}
|
|
696
|
+
throw error;
|
|
697
|
+
}
|
|
698
|
+
}
|
|
633
699
|
async cloneRepo(workspace, token) {
|
|
634
700
|
const cloneUrl = token ? this.buildAuthenticatedUrl(workspace.repo, token) : workspace.repo;
|
|
635
701
|
await this.execInDir(
|
|
@@ -653,11 +719,11 @@ var WorkspaceService = class {
|
|
|
653
719
|
async configureGit(workspace) {
|
|
654
720
|
await this.execInDir(workspace.path, 'git config user.name "Workspace Agent"');
|
|
655
721
|
await this.execInDir(workspace.path, 'git config user.email "agent@workspace.local"');
|
|
656
|
-
if (!workspace.credential.token) {
|
|
722
|
+
if (!workspace.credential || !workspace.credential.token) {
|
|
657
723
|
this.log(
|
|
658
724
|
"debug",
|
|
659
725
|
{ workspaceId: workspace.id },
|
|
660
|
-
"Using SSH authentication, skipping credential helper"
|
|
726
|
+
workspace.credential ? "Using SSH authentication, skipping credential helper" : "No credentials (public repo), skipping credential helper"
|
|
661
727
|
);
|
|
662
728
|
return;
|
|
663
729
|
}
|
|
@@ -683,9 +749,19 @@ var WorkspaceService = class {
|
|
|
683
749
|
);
|
|
684
750
|
}
|
|
685
751
|
async pushBranch(workspace) {
|
|
752
|
+
if (!workspace.credential) {
|
|
753
|
+
throw new Error(
|
|
754
|
+
"Push requires authentication. This workspace was cloned from a public repository without credentials."
|
|
755
|
+
);
|
|
756
|
+
}
|
|
686
757
|
await this.execInDir(workspace.path, `git push -u origin ${workspace.branch.name}`);
|
|
687
758
|
}
|
|
688
759
|
async createPullRequest(workspace, config) {
|
|
760
|
+
if (!workspace.credential) {
|
|
761
|
+
throw new Error(
|
|
762
|
+
"Pull request creation requires authentication. This workspace was cloned from a public repository without credentials."
|
|
763
|
+
);
|
|
764
|
+
}
|
|
689
765
|
const repoInfo = this.parseRepo(workspace.repo);
|
|
690
766
|
if (!repoInfo) {
|
|
691
767
|
throw new Error(`Invalid repository format: ${workspace.repo}`);
|