@adhdev/daemon-core 0.9.61 → 0.9.63
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/git/git-commands.d.ts +16 -0
- package/dist/git/git-types.d.ts +1 -1
- package/dist/index.js +61 -2
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +61 -2
- package/dist/index.mjs.map +1 -1
- package/node_modules/@adhdev/session-host-core/package.json +1 -1
- package/package.json +1 -1
- package/src/git/git-commands.ts +84 -1
- package/src/git/git-types.ts +2 -1
package/package.json
CHANGED
package/src/git/git-commands.ts
CHANGED
|
@@ -53,6 +53,14 @@ export interface GitStashPushResult extends GitRepoIdentity {
|
|
|
53
53
|
lastCheckedAt: number;
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
+
export interface GitPushResult extends GitRepoIdentity {
|
|
57
|
+
remote: string;
|
|
58
|
+
branch: string;
|
|
59
|
+
output: string;
|
|
60
|
+
newBranch: boolean;
|
|
61
|
+
lastCheckedAt: number;
|
|
62
|
+
}
|
|
63
|
+
|
|
56
64
|
export interface GitCommandServices {
|
|
57
65
|
getStatus?: (params: { workspace: string }) => Promise<GitRepoStatus> | GitRepoStatus;
|
|
58
66
|
getDiffSummary?: (params: { workspace: string; staged?: boolean }) => Promise<GitDiffSummary> | GitDiffSummary;
|
|
@@ -88,6 +96,7 @@ export interface GitCommandServices {
|
|
|
88
96
|
stashPop?: (params: { workspace: string; stashRef?: string }) => Promise<void>;
|
|
89
97
|
checkoutFiles?: (params: { workspace: string; paths: string[] }) => Promise<{ checkedOut: string[] }>;
|
|
90
98
|
getRemoteUrl?: (params: { workspace: string; remote?: string }) => Promise<{ remoteUrl: string; remote: string }>;
|
|
99
|
+
push?: (params: { workspace: string; remote?: string; branch?: string; setUpstream?: boolean }) => Promise<GitPushResult>;
|
|
91
100
|
}
|
|
92
101
|
|
|
93
102
|
type GitCommandFailure = {
|
|
@@ -107,7 +116,8 @@ type GitCommandSuccess =
|
|
|
107
116
|
| { success: true; stash: GitStashPushResult }
|
|
108
117
|
| { success: true; stashPopped: true }
|
|
109
118
|
| { success: true; checkedOut: string[] }
|
|
110
|
-
| { success: true; remoteUrl: string; remote: string }
|
|
119
|
+
| { success: true; remoteUrl: string; remote: string }
|
|
120
|
+
| { success: true; push: GitPushResult };
|
|
111
121
|
|
|
112
122
|
export type GitCommandResult = GitCommandSuccess | GitCommandFailure;
|
|
113
123
|
|
|
@@ -123,6 +133,7 @@ const GIT_COMMAND_NAMES = new Set<GitCommandName>([
|
|
|
123
133
|
'git_stash_pop',
|
|
124
134
|
'git_checkout_files',
|
|
125
135
|
'git_remote_url',
|
|
136
|
+
'git_push',
|
|
126
137
|
]);
|
|
127
138
|
|
|
128
139
|
const SNAPSHOT_REASONS = new Set<GitSnapshotReason>([
|
|
@@ -175,6 +186,8 @@ export function createDefaultGitCommandServices(): GitCommandServices {
|
|
|
175
186
|
stashPop: async ({ workspace, stashRef }) => gitStashPop(workspace, stashRef),
|
|
176
187
|
checkoutFiles: async ({ workspace, paths }) => gitCheckoutFiles(workspace, paths),
|
|
177
188
|
getRemoteUrl: async ({ workspace, remote = 'origin' }) => gitGetRemoteUrl(workspace, remote),
|
|
189
|
+
push: async ({ workspace, remote = 'origin', branch, setUpstream = false }) =>
|
|
190
|
+
gitPush(workspace, remote, branch, setUpstream),
|
|
178
191
|
};
|
|
179
192
|
}
|
|
180
193
|
|
|
@@ -385,6 +398,21 @@ export async function handleGitCommand(
|
|
|
385
398
|
return { success: true, remoteUrl: remoteResult.remoteUrl, remote: remoteResult.remote };
|
|
386
399
|
}
|
|
387
400
|
|
|
401
|
+
case 'git_push': {
|
|
402
|
+
if (!services.push) return serviceNotImplemented(command);
|
|
403
|
+
const remote = typeof args?.remote === 'string' && args.remote.trim() ? args.remote.trim() : 'origin';
|
|
404
|
+
const branch = typeof args?.branch === 'string' && args.branch.trim() ? args.branch.trim() : undefined;
|
|
405
|
+
const setUpstream = Boolean(args?.setUpstream);
|
|
406
|
+
if (!/^[a-zA-Z0-9_.\-]+$/.test(remote)) {
|
|
407
|
+
return failure('invalid_args', 'remote must contain only alphanumeric characters, dots, hyphens, and underscores');
|
|
408
|
+
}
|
|
409
|
+
if (branch !== undefined && !/^[a-zA-Z0-9/_.\-]+$/.test(branch)) {
|
|
410
|
+
return failure('invalid_args', 'branch must contain only alphanumeric characters, slashes, dots, hyphens, and underscores');
|
|
411
|
+
}
|
|
412
|
+
const pushResult = await runService(() => services.push!({ workspace, remote, branch, setUpstream }));
|
|
413
|
+
return 'success' in pushResult ? pushResult : { success: true, push: pushResult };
|
|
414
|
+
}
|
|
415
|
+
|
|
388
416
|
default:
|
|
389
417
|
return failure('invalid_args', `Unknown Git command: ${command}`);
|
|
390
418
|
}
|
|
@@ -512,6 +540,61 @@ async function gitGetRemoteUrl(workspace: string, remote: string): Promise<{ rem
|
|
|
512
540
|
return { remoteUrl, remote };
|
|
513
541
|
}
|
|
514
542
|
|
|
543
|
+
async function gitPush(
|
|
544
|
+
workspace: string,
|
|
545
|
+
remote: string,
|
|
546
|
+
branch: string | undefined,
|
|
547
|
+
setUpstream: boolean,
|
|
548
|
+
): Promise<GitPushResult> {
|
|
549
|
+
const lastCheckedAt = Date.now();
|
|
550
|
+
const repo = await resolveGitRepository(workspace);
|
|
551
|
+
const repoRoot = repo.repoRoot!;
|
|
552
|
+
|
|
553
|
+
// Resolve branch name if not provided
|
|
554
|
+
let resolvedBranch = branch;
|
|
555
|
+
if (!resolvedBranch) {
|
|
556
|
+
const branchResult = await runGit(repo, ['symbolic-ref', '--short', 'HEAD'], { cwd: repoRoot });
|
|
557
|
+
resolvedBranch = branchResult.stdout.trim();
|
|
558
|
+
if (!resolvedBranch) {
|
|
559
|
+
throw new GitCommandError('git_command_failed', 'Cannot push: not on a branch (detached HEAD)');
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
const pushArgs = ['push'];
|
|
564
|
+
if (setUpstream) pushArgs.push('--set-upstream');
|
|
565
|
+
pushArgs.push(remote, resolvedBranch);
|
|
566
|
+
|
|
567
|
+
let output = '';
|
|
568
|
+
let newBranch = false;
|
|
569
|
+
try {
|
|
570
|
+
const result = await runGit(repo, pushArgs, { cwd: repoRoot });
|
|
571
|
+
output = (result.stdout + result.stderr).trim();
|
|
572
|
+
newBranch = /\[new branch\]/i.test(output);
|
|
573
|
+
} catch (err: any) {
|
|
574
|
+
const errOutput = (err?.stdout ?? '') + (err?.stderr ?? '');
|
|
575
|
+
// --set-upstream hint: retry with --set-upstream automatically
|
|
576
|
+
if (!setUpstream && /no upstream branch|set-upstream/i.test(errOutput)) {
|
|
577
|
+
const retryArgs = ['push', '--set-upstream', remote, resolvedBranch];
|
|
578
|
+
const retryResult = await runGit(repo, retryArgs, { cwd: repoRoot });
|
|
579
|
+
output = (retryResult.stdout + retryResult.stderr).trim();
|
|
580
|
+
newBranch = /\[new branch\]/i.test(output);
|
|
581
|
+
} else {
|
|
582
|
+
throw new GitCommandError('git_command_failed', errOutput || err?.message || 'git push failed');
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
return {
|
|
587
|
+
workspace: repo.workspace,
|
|
588
|
+
repoRoot,
|
|
589
|
+
isGitRepo: true,
|
|
590
|
+
remote,
|
|
591
|
+
branch: resolvedBranch,
|
|
592
|
+
output,
|
|
593
|
+
newBranch,
|
|
594
|
+
lastCheckedAt,
|
|
595
|
+
};
|
|
596
|
+
}
|
|
597
|
+
|
|
515
598
|
function formatOptionalGitLogRangeArg(flag: '--since' | '--until', value: string | undefined): string[] {
|
|
516
599
|
return value ? [`${flag}=${value}`] : [];
|
|
517
600
|
}
|
package/src/git/git-types.ts
CHANGED