@gtc6244/immediacy-daemon 0.1.0
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/src/actions.d.ts +22 -0
- package/dist/src/actions.js +44 -0
- package/dist/src/actions.js.map +1 -0
- package/dist/src/agent/agent.d.ts +89 -0
- package/dist/src/agent/agent.js +22 -0
- package/dist/src/agent/agent.js.map +1 -0
- package/dist/src/agent/claude.d.ts +70 -0
- package/dist/src/agent/claude.js +404 -0
- package/dist/src/agent/claude.js.map +1 -0
- package/dist/src/agent/codex.d.ts +44 -0
- package/dist/src/agent/codex.js +303 -0
- package/dist/src/agent/codex.js.map +1 -0
- package/dist/src/agent/mock.d.ts +31 -0
- package/dist/src/agent/mock.js +155 -0
- package/dist/src/agent/mock.js.map +1 -0
- package/dist/src/agent/model-error.d.ts +8 -0
- package/dist/src/agent/model-error.js +25 -0
- package/dist/src/agent/model-error.js.map +1 -0
- package/dist/src/agent/openrouter.d.ts +38 -0
- package/dist/src/agent/openrouter.js +60 -0
- package/dist/src/agent/openrouter.js.map +1 -0
- package/dist/src/agent/workspace-scope.d.ts +25 -0
- package/dist/src/agent/workspace-scope.js +71 -0
- package/dist/src/agent/workspace-scope.js.map +1 -0
- package/dist/src/allowlist.d.ts +56 -0
- package/dist/src/allowlist.js +141 -0
- package/dist/src/allowlist.js.map +1 -0
- package/dist/src/chatlog.d.ts +50 -0
- package/dist/src/chatlog.js +179 -0
- package/dist/src/chatlog.js.map +1 -0
- package/dist/src/cli/paths.d.ts +40 -0
- package/dist/src/cli/paths.js +76 -0
- package/dist/src/cli/paths.js.map +1 -0
- package/dist/src/cli/service.d.ts +20 -0
- package/dist/src/cli/service.js +245 -0
- package/dist/src/cli/service.js.map +1 -0
- package/dist/src/cli.d.ts +2 -0
- package/dist/src/cli.js +227 -0
- package/dist/src/cli.js.map +1 -0
- package/dist/src/config.d.ts +33 -0
- package/dist/src/config.js +122 -0
- package/dist/src/config.js.map +1 -0
- package/dist/src/credentials.d.ts +38 -0
- package/dist/src/credentials.js +120 -0
- package/dist/src/credentials.js.map +1 -0
- package/dist/src/crypto.d.ts +49 -0
- package/dist/src/crypto.js +202 -0
- package/dist/src/crypto.js.map +1 -0
- package/dist/src/daemon-identity.d.ts +31 -0
- package/dist/src/daemon-identity.js +97 -0
- package/dist/src/daemon-identity.js.map +1 -0
- package/dist/src/envelope.d.ts +14 -0
- package/dist/src/envelope.js +28 -0
- package/dist/src/envelope.js.map +1 -0
- package/dist/src/events.d.ts +40 -0
- package/dist/src/events.js +24 -0
- package/dist/src/events.js.map +1 -0
- package/dist/src/forward.d.ts +51 -0
- package/dist/src/forward.js +170 -0
- package/dist/src/forward.js.map +1 -0
- package/dist/src/fs-scope.d.ts +17 -0
- package/dist/src/fs-scope.js +47 -0
- package/dist/src/fs-scope.js.map +1 -0
- package/dist/src/github.d.ts +70 -0
- package/dist/src/github.js +178 -0
- package/dist/src/github.js.map +1 -0
- package/dist/src/gitops.d.ts +113 -0
- package/dist/src/gitops.js +557 -0
- package/dist/src/gitops.js.map +1 -0
- package/dist/src/hub.d.ts +50 -0
- package/dist/src/hub.js +92 -0
- package/dist/src/hub.js.map +1 -0
- package/dist/src/index.d.ts +22 -0
- package/dist/src/index.js +56 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/jobs/scheduler.d.ts +94 -0
- package/dist/src/jobs/scheduler.js +373 -0
- package/dist/src/jobs/scheduler.js.map +1 -0
- package/dist/src/jobs/store.d.ts +33 -0
- package/dist/src/jobs/store.js +111 -0
- package/dist/src/jobs/store.js.map +1 -0
- package/dist/src/log.d.ts +61 -0
- package/dist/src/log.js +166 -0
- package/dist/src/log.js.map +1 -0
- package/dist/src/migrate-state-dir.d.ts +1 -0
- package/dist/src/migrate-state-dir.js +47 -0
- package/dist/src/migrate-state-dir.js.map +1 -0
- package/dist/src/models.d.ts +36 -0
- package/dist/src/models.js +71 -0
- package/dist/src/models.js.map +1 -0
- package/dist/src/permission-gate.d.ts +48 -0
- package/dist/src/permission-gate.js +93 -0
- package/dist/src/permission-gate.js.map +1 -0
- package/dist/src/permission-scope.d.ts +77 -0
- package/dist/src/permission-scope.js +244 -0
- package/dist/src/permission-scope.js.map +1 -0
- package/dist/src/ports.d.ts +71 -0
- package/dist/src/ports.js +216 -0
- package/dist/src/ports.js.map +1 -0
- package/dist/src/projects.d.ts +83 -0
- package/dist/src/projects.js +205 -0
- package/dist/src/projects.js.map +1 -0
- package/dist/src/protocol.d.ts +1226 -0
- package/dist/src/protocol.js +16 -0
- package/dist/src/protocol.js.map +1 -0
- package/dist/src/repo-sync.d.ts +49 -0
- package/dist/src/repo-sync.js +83 -0
- package/dist/src/repo-sync.js.map +1 -0
- package/dist/src/server.d.ts +33 -0
- package/dist/src/server.js +973 -0
- package/dist/src/server.js.map +1 -0
- package/dist/src/terminal.d.ts +32 -0
- package/dist/src/terminal.js +92 -0
- package/dist/src/terminal.js.map +1 -0
- package/dist/src/titler.d.ts +15 -0
- package/dist/src/titler.js +72 -0
- package/dist/src/titler.js.map +1 -0
- package/dist/src/types.d.ts +99 -0
- package/dist/src/types.js +3 -0
- package/dist/src/types.js.map +1 -0
- package/dist/src/usage-limit.d.ts +49 -0
- package/dist/src/usage-limit.js +83 -0
- package/dist/src/usage-limit.js.map +1 -0
- package/dist/src/usage.d.ts +23 -0
- package/dist/src/usage.js +63 -0
- package/dist/src/usage.js.map +1 -0
- package/dist/src/workspace.d.ts +303 -0
- package/dist/src/workspace.js +1086 -0
- package/dist/src/workspace.js.map +1 -0
- package/dist/src/worktree.d.ts +133 -0
- package/dist/src/worktree.js +561 -0
- package/dist/src/worktree.js.map +1 -0
- package/package.json +67 -0
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GitHub integration via the `gh` CLI.
|
|
3
|
+
*
|
|
4
|
+
* Why gh, not a stored token: the daemon runs on the user's Mac where `gh` is
|
|
5
|
+
* already authenticated. Reusing it means the GitHub token never touches the
|
|
6
|
+
* phone, the wire, or this source — it stays in gh's keychain (§ no secrets in
|
|
7
|
+
* source / single-user). The daemon just shells out.
|
|
8
|
+
*
|
|
9
|
+
* Flow: list the user's repos → user picks one → `cloneInto` clones it into the
|
|
10
|
+
* project's managed directory → the normal worktree path forks off that clone.
|
|
11
|
+
*/
|
|
12
|
+
import { execFile } from "node:child_process";
|
|
13
|
+
import { mkdir } from "node:fs/promises";
|
|
14
|
+
import { homedir } from "node:os";
|
|
15
|
+
import { dirname, join } from "node:path";
|
|
16
|
+
import { promisify } from "node:util";
|
|
17
|
+
const exec = promisify(execFile);
|
|
18
|
+
/**
|
|
19
|
+
* Legacy clone cache. New GitHub projects clone into the managed projects root
|
|
20
|
+
* (see projects.ts); this constant survives only so pre-existing project
|
|
21
|
+
* records whose repo path points here are still recognised as cached clones.
|
|
22
|
+
*/
|
|
23
|
+
export const REPO_CACHE = process.env.REPO_CACHE ?? join(homedir(), ".immediacy", "repos");
|
|
24
|
+
/** Is `gh` installed AND logged in? Drives whether the app shows the picker. */
|
|
25
|
+
export async function status() {
|
|
26
|
+
try {
|
|
27
|
+
await exec("gh", ["--version"]);
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
return { available: false, authenticated: false };
|
|
31
|
+
}
|
|
32
|
+
try {
|
|
33
|
+
// `gh auth status` exits non-zero when not logged in.
|
|
34
|
+
await exec("gh", ["auth", "status"]);
|
|
35
|
+
const { stdout } = await exec("gh", ["api", "user", "--jq", ".login"]);
|
|
36
|
+
return { available: true, authenticated: true, user: stdout.trim() };
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
return { available: true, authenticated: false };
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* List every repo the authenticated user can access, most-recently-pushed
|
|
44
|
+
* first.
|
|
45
|
+
*
|
|
46
|
+
* Why `gh api /user/repos` and not `gh repo list`: `gh repo list` only returns
|
|
47
|
+
* repos the user *owns*, so repos where they're a collaborator or org member
|
|
48
|
+
* never reach the picker. `/user/repos?affiliation=owner,collaborator,
|
|
49
|
+
* organization_member` returns the full set the account has access to. We reshape
|
|
50
|
+
* the REST fields into our `GhRepoJson` shape (jq runs per page; `--paginate`
|
|
51
|
+
* follows Link headers, so output is newline-delimited JSON objects).
|
|
52
|
+
*/
|
|
53
|
+
export async function listRepos(limit = 100) {
|
|
54
|
+
const { stdout } = await exec("gh", [
|
|
55
|
+
"api",
|
|
56
|
+
"--paginate",
|
|
57
|
+
"--jq",
|
|
58
|
+
".[] | { nameWithOwner: .full_name, name: .name, owner: { login: .owner.login }, description: .description, isPrivate: .private, defaultBranch: .default_branch, url: .html_url }",
|
|
59
|
+
"/user/repos?affiliation=owner,collaborator,organization_member&sort=pushed&per_page=100",
|
|
60
|
+
], { maxBuffer: 32 * 1024 * 1024 });
|
|
61
|
+
const cap = Math.min(Math.max(limit, 1), 1000);
|
|
62
|
+
const raw = stdout
|
|
63
|
+
.split("\n")
|
|
64
|
+
.filter((line) => line.trim() !== "")
|
|
65
|
+
.map((line) => JSON.parse(line));
|
|
66
|
+
return raw.slice(0, cap).map((r) => ({
|
|
67
|
+
fullName: r.nameWithOwner,
|
|
68
|
+
name: r.name,
|
|
69
|
+
owner: r.owner?.login ?? r.nameWithOwner.split("/")[0] ?? "",
|
|
70
|
+
description: r.description ?? "",
|
|
71
|
+
isPrivate: r.isPrivate,
|
|
72
|
+
defaultBranch: r.defaultBranch ?? "HEAD",
|
|
73
|
+
url: r.url,
|
|
74
|
+
}));
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Clone a GitHub repo into `dest` via `gh` (uses gh's auth, so private repos
|
|
78
|
+
* work). The caller owns `dest` — it lives in the managed projects root, so the
|
|
79
|
+
* client never chooses where the clone lands.
|
|
80
|
+
*/
|
|
81
|
+
export async function cloneInto(fullName, dest) {
|
|
82
|
+
await mkdir(dirname(dest), { recursive: true });
|
|
83
|
+
await exec("gh", ["repo", "clone", fullName, dest], {
|
|
84
|
+
maxBuffer: 64 * 1024 * 1024,
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* List a project's open pull requests, newest first. Runs `gh` with the repo
|
|
89
|
+
* clone as its cwd so it targets that repo's `origin` without us threading the
|
|
90
|
+
* `fullName` through — the same keychain-auth stance as the rest of this file.
|
|
91
|
+
* Returns [] rather than throwing when `gh` is absent/unauthenticated or the
|
|
92
|
+
* project has no GitHub remote, so the picker just shows "no open PRs".
|
|
93
|
+
*/
|
|
94
|
+
export async function listPullRequests(repoPath) {
|
|
95
|
+
try {
|
|
96
|
+
const { stdout } = await exec("gh", [
|
|
97
|
+
"pr",
|
|
98
|
+
"list",
|
|
99
|
+
"--state",
|
|
100
|
+
"open",
|
|
101
|
+
"--limit",
|
|
102
|
+
"100",
|
|
103
|
+
"--json",
|
|
104
|
+
"number,title,headRefName,author,url,isDraft",
|
|
105
|
+
], { cwd: repoPath, maxBuffer: 16 * 1024 * 1024 });
|
|
106
|
+
const raw = JSON.parse(stdout || "[]");
|
|
107
|
+
return raw.map((p) => ({
|
|
108
|
+
number: p.number,
|
|
109
|
+
title: p.title,
|
|
110
|
+
headRefName: p.headRefName,
|
|
111
|
+
author: p.author?.login ?? "",
|
|
112
|
+
url: p.url,
|
|
113
|
+
isDraft: p.isDraft,
|
|
114
|
+
}));
|
|
115
|
+
}
|
|
116
|
+
catch {
|
|
117
|
+
return [];
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Resolve an open PR's head branch name. Used by the "create worktree from PR"
|
|
122
|
+
* flow to know which ref to check out. Throws (unlike the list calls) because
|
|
123
|
+
* the caller can't proceed without it.
|
|
124
|
+
*/
|
|
125
|
+
export async function prHeadRef(repoPath, prNumber) {
|
|
126
|
+
const { stdout } = await exec("gh", ["pr", "view", String(prNumber), "--json", "headRefName", "--jq", ".headRefName"], { cwd: repoPath });
|
|
127
|
+
const ref = stdout.trim();
|
|
128
|
+
if (!ref)
|
|
129
|
+
throw new Error(`could not resolve head branch for PR #${prNumber}`);
|
|
130
|
+
return ref;
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* List a project's open issues (with bodies), newest first. Bodies ride along
|
|
134
|
+
* so the "create worktree from an issue" flow can seed and let the user confirm
|
|
135
|
+
* the new worktree's task without a second round-trip. Best-effort like
|
|
136
|
+
* {@link listPullRequests} — returns [] on any `gh` failure.
|
|
137
|
+
*/
|
|
138
|
+
export async function listIssues(repoPath) {
|
|
139
|
+
try {
|
|
140
|
+
const { stdout } = await exec("gh", ["issue", "list", "--state", "open", "--limit", "100", "--json", "number,title,body,author,url"], { cwd: repoPath, maxBuffer: 16 * 1024 * 1024 });
|
|
141
|
+
const raw = JSON.parse(stdout || "[]");
|
|
142
|
+
return raw.map((i) => ({
|
|
143
|
+
number: i.number,
|
|
144
|
+
title: i.title,
|
|
145
|
+
body: i.body ?? "",
|
|
146
|
+
author: i.author?.login ?? "",
|
|
147
|
+
url: i.url,
|
|
148
|
+
}));
|
|
149
|
+
}
|
|
150
|
+
catch {
|
|
151
|
+
return [];
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Open a GitHub issue in the workspace's repo via `gh issue create` and return
|
|
156
|
+
* its URL — the mirror of `prCreate`. The agent's produced plan/document is the
|
|
157
|
+
* `body`. Runs with the worktree as cwd so `gh` targets the right repo.
|
|
158
|
+
*/
|
|
159
|
+
export async function createIssue(repoPath, title, body) {
|
|
160
|
+
const { stdout } = await exec("gh", ["issue", "create", "--title", title, "--body", body], { cwd: repoPath });
|
|
161
|
+
// `gh issue create` prints the new issue's URL as its last line.
|
|
162
|
+
return stdout.trim().split("\n").pop() ?? "";
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Best-effort refresh of an existing clone's base branch. Never throws, so a
|
|
166
|
+
* daemon that's offline keeps using the clone it already has.
|
|
167
|
+
*/
|
|
168
|
+
export async function refreshRepo(repoPath) {
|
|
169
|
+
try {
|
|
170
|
+
await exec("git", ["-C", repoPath, "fetch", "--all", "--prune"], {
|
|
171
|
+
maxBuffer: 16 * 1024 * 1024,
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
catch {
|
|
175
|
+
/* offline / transient — keep using the existing clone */
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
//# sourceMappingURL=github.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"github.js","sourceRoot":"","sources":["../../src/github.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Git review-and-merge operations for a workspace: status, commit, push, PR.
|
|
3
|
+
*
|
|
4
|
+
* These power the Conductor-style "review the diff → commit → push → open a
|
|
5
|
+
* PR" path from a pure-front-end client. Everything runs inside the worktree;
|
|
6
|
+
* the PR goes through the `gh` CLI so its keychain auth is reused (same stance
|
|
7
|
+
* as github.ts — no tokens on the wire or in source).
|
|
8
|
+
*/
|
|
9
|
+
import type { GitStatusResultPayload, GitResultPayload } from "./protocol.js";
|
|
10
|
+
import type { WorkspaceRecord } from "./types.js";
|
|
11
|
+
export declare function originUrl(repoPath: string): Promise<string | undefined>;
|
|
12
|
+
/** Drop a cached origin URL (e.g. after a remote is added/changed). */
|
|
13
|
+
export declare function forgetOriginUrl(repoPath: string): void;
|
|
14
|
+
/** Ahead/behind + dirty-file summary against the workspace's merge-to ref. */
|
|
15
|
+
export declare function gitStatus(record: WorkspaceRecord): Promise<GitStatusResultPayload>;
|
|
16
|
+
/** Stage everything and commit. Fails soft ("nothing to commit") into ok:false. */
|
|
17
|
+
export declare function gitCommit(record: WorkspaceRecord, message: string): Promise<GitResultPayload>;
|
|
18
|
+
/**
|
|
19
|
+
* Push the workspace branch. When `autoSetupRemote` is true (the default and the
|
|
20
|
+
* git.worktreePushAutoSetupRemote config default), sets the upstream on first
|
|
21
|
+
* push with `-u`; when false, pushes without configuring the upstream.
|
|
22
|
+
*/
|
|
23
|
+
export declare function gitPush(record: WorkspaceRecord, autoSetupRemote?: boolean): Promise<GitResultPayload>;
|
|
24
|
+
/** The remote's view of a branch's most recent PR ("NONE" = none / `gh` failed). */
|
|
25
|
+
export type PrState = "OPEN" | "MERGED" | "CLOSED" | "NONE";
|
|
26
|
+
/**
|
|
27
|
+
* A branch's most recent PR as seen through `gh`. `number`/`url`/`headRef` are
|
|
28
|
+
* null exactly when no PR exists (`state === "NONE"`); when a PR exists they
|
|
29
|
+
* carry its number, web URL, and head branch name so callers can surface a link
|
|
30
|
+
* and reconcile the workspace label to the PR's branch.
|
|
31
|
+
*/
|
|
32
|
+
export interface PrInfo {
|
|
33
|
+
state: PrState;
|
|
34
|
+
number: number | null;
|
|
35
|
+
url: string | null;
|
|
36
|
+
/** The PR's head branch (`headRefName`). */
|
|
37
|
+
headRef: string | null;
|
|
38
|
+
/** The PR's title as shown on GitHub. */
|
|
39
|
+
title: string | null;
|
|
40
|
+
}
|
|
41
|
+
/** Default freshness window for a branch's cached PR state. */
|
|
42
|
+
export declare const DEFAULT_PR_STATE_TTL_MS = 60000;
|
|
43
|
+
/**
|
|
44
|
+
* The workspace branch's PR (state + number/url/head) via `gh pr view <branch>`
|
|
45
|
+
* (reuses keychain auth, same stance as prCreate), cached per branch to bound
|
|
46
|
+
* `gh` invocations on the status-poll path: at most one lookup per `ttlMs`, and
|
|
47
|
+
* concurrent callers for the same branch (a merged-check, a hasPr probe, and the
|
|
48
|
+
* label-reconcile in the same poll) ride a single in-flight request. Best effort
|
|
49
|
+
* throughout — a failed lookup resolves to {@link NO_PR} and the throttle still
|
|
50
|
+
* advances, so an unreachable remote isn't retried every poll.
|
|
51
|
+
*/
|
|
52
|
+
export declare function prInfo(record: WorkspaceRecord, ttlMs?: number): Promise<PrInfo>;
|
|
53
|
+
/** Just the {@link prInfo} state enum — the common case for merge/archive gates. */
|
|
54
|
+
export declare function prState(record: WorkspaceRecord, ttlMs?: number): Promise<PrState>;
|
|
55
|
+
/**
|
|
56
|
+
* Forget a branch's cached PR state so the next {@link prState} re-queries `gh`.
|
|
57
|
+
* Called after opening or merging a PR so the buttons re-key to the new state on
|
|
58
|
+
* the very next status poll instead of lingering until the TTL lapses.
|
|
59
|
+
*/
|
|
60
|
+
export declare function invalidatePrState(record: WorkspaceRecord): void;
|
|
61
|
+
/** Testing/reset hook: forget all cached PR state. */
|
|
62
|
+
export declare function resetPrStateCache(): void;
|
|
63
|
+
/**
|
|
64
|
+
* Whether the workspace branch's PR has been merged on the remote. Best effort:
|
|
65
|
+
* any failure (no PR, `gh` unauthenticated/absent, network) reads as not-merged
|
|
66
|
+
* so the caller simply doesn't auto-archive.
|
|
67
|
+
*/
|
|
68
|
+
export declare function detectMerged(record: WorkspaceRecord): Promise<boolean>;
|
|
69
|
+
/**
|
|
70
|
+
* Open a PR for the workspace branch via `gh pr create`. If one already exists
|
|
71
|
+
* for this branch, surface its URL instead of failing.
|
|
72
|
+
*/
|
|
73
|
+
export declare function prCreate(record: WorkspaceRecord, title: string, body?: string): Promise<GitResultPayload>;
|
|
74
|
+
/**
|
|
75
|
+
* Merge the workspace branch's open PR on the remote via `gh pr merge --merge`.
|
|
76
|
+
* Backs the "Merge" button, which surfaces only for an open PR that is clean
|
|
77
|
+
* (no conflicts with the base). On success we drop the cached PR state so the
|
|
78
|
+
* next status poll sees the PR as merged and swaps Merge for the Archive
|
|
79
|
+
* affordance. Best effort on the error path, same keychain-auth stance as
|
|
80
|
+
* prCreate.
|
|
81
|
+
*/
|
|
82
|
+
export declare function prMerge(record: WorkspaceRecord): Promise<GitResultPayload>;
|
|
83
|
+
/**
|
|
84
|
+
* Reconcile the worktree with its merge-to branch. Used by the "Resolve"
|
|
85
|
+
* action, which surfaces only when the base has advanced past this branch
|
|
86
|
+
* (`behind > 0`) and the tree is clean.
|
|
87
|
+
*
|
|
88
|
+
* We fetch `origin/<base>` first so we reconcile against what's actually on the
|
|
89
|
+
* remote, then merge that ref (falling back to the local base when there is no
|
|
90
|
+
* remote-tracking ref, e.g. offline or base never pushed). A clean merge lands
|
|
91
|
+
* a merge commit. A conflicting merge is *left in progress on purpose*: the
|
|
92
|
+
* client drops into its in-app conflict flow (see `gitMerge`) to pick a side
|
|
93
|
+
* per file and commit, or abort. We refuse up front if the tree is dirty, since
|
|
94
|
+
* `git merge` would bail anyway with a less friendly message.
|
|
95
|
+
*/
|
|
96
|
+
export declare function gitResolve(record: WorkspaceRecord): Promise<GitResultPayload>;
|
|
97
|
+
/**
|
|
98
|
+
* Drive an in-progress merge from the client's conflict UI:
|
|
99
|
+
* - `ours` — keep the workspace branch's version of the conflicting files
|
|
100
|
+
* - `theirs` — keep the merged-in base branch's version
|
|
101
|
+
* - `commit` — finalize the merge commit (refuses while conflicts remain)
|
|
102
|
+
* - `abort` — roll the merge back, restoring the pre-merge worktree
|
|
103
|
+
*
|
|
104
|
+
* `ours`/`theirs` default to every conflicting file; pass `paths` to resolve a
|
|
105
|
+
* subset (per-file resolution). After picking a side we `git add` the files so
|
|
106
|
+
* git marks them resolved.
|
|
107
|
+
*/
|
|
108
|
+
export declare function gitMerge(record: WorkspaceRecord, action: "ours" | "theirs" | "commit" | "abort", paths?: string[]): Promise<GitResultPayload>;
|
|
109
|
+
/**
|
|
110
|
+
* Reveal the worktree on this Mac: Finder, Terminal, or the user's editor.
|
|
111
|
+
* Editor prefers the VS Code CLI when installed, then falls back to `open -a`.
|
|
112
|
+
*/
|
|
113
|
+
export declare function openWorktree(record: WorkspaceRecord, target: "finder" | "terminal" | "editor"): Promise<void>;
|