@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.
Files changed (133) hide show
  1. package/dist/src/actions.d.ts +22 -0
  2. package/dist/src/actions.js +44 -0
  3. package/dist/src/actions.js.map +1 -0
  4. package/dist/src/agent/agent.d.ts +89 -0
  5. package/dist/src/agent/agent.js +22 -0
  6. package/dist/src/agent/agent.js.map +1 -0
  7. package/dist/src/agent/claude.d.ts +70 -0
  8. package/dist/src/agent/claude.js +404 -0
  9. package/dist/src/agent/claude.js.map +1 -0
  10. package/dist/src/agent/codex.d.ts +44 -0
  11. package/dist/src/agent/codex.js +303 -0
  12. package/dist/src/agent/codex.js.map +1 -0
  13. package/dist/src/agent/mock.d.ts +31 -0
  14. package/dist/src/agent/mock.js +155 -0
  15. package/dist/src/agent/mock.js.map +1 -0
  16. package/dist/src/agent/model-error.d.ts +8 -0
  17. package/dist/src/agent/model-error.js +25 -0
  18. package/dist/src/agent/model-error.js.map +1 -0
  19. package/dist/src/agent/openrouter.d.ts +38 -0
  20. package/dist/src/agent/openrouter.js +60 -0
  21. package/dist/src/agent/openrouter.js.map +1 -0
  22. package/dist/src/agent/workspace-scope.d.ts +25 -0
  23. package/dist/src/agent/workspace-scope.js +71 -0
  24. package/dist/src/agent/workspace-scope.js.map +1 -0
  25. package/dist/src/allowlist.d.ts +56 -0
  26. package/dist/src/allowlist.js +141 -0
  27. package/dist/src/allowlist.js.map +1 -0
  28. package/dist/src/chatlog.d.ts +50 -0
  29. package/dist/src/chatlog.js +179 -0
  30. package/dist/src/chatlog.js.map +1 -0
  31. package/dist/src/cli/paths.d.ts +40 -0
  32. package/dist/src/cli/paths.js +76 -0
  33. package/dist/src/cli/paths.js.map +1 -0
  34. package/dist/src/cli/service.d.ts +20 -0
  35. package/dist/src/cli/service.js +245 -0
  36. package/dist/src/cli/service.js.map +1 -0
  37. package/dist/src/cli.d.ts +2 -0
  38. package/dist/src/cli.js +227 -0
  39. package/dist/src/cli.js.map +1 -0
  40. package/dist/src/config.d.ts +33 -0
  41. package/dist/src/config.js +122 -0
  42. package/dist/src/config.js.map +1 -0
  43. package/dist/src/credentials.d.ts +38 -0
  44. package/dist/src/credentials.js +120 -0
  45. package/dist/src/credentials.js.map +1 -0
  46. package/dist/src/crypto.d.ts +49 -0
  47. package/dist/src/crypto.js +202 -0
  48. package/dist/src/crypto.js.map +1 -0
  49. package/dist/src/daemon-identity.d.ts +31 -0
  50. package/dist/src/daemon-identity.js +97 -0
  51. package/dist/src/daemon-identity.js.map +1 -0
  52. package/dist/src/envelope.d.ts +14 -0
  53. package/dist/src/envelope.js +28 -0
  54. package/dist/src/envelope.js.map +1 -0
  55. package/dist/src/events.d.ts +40 -0
  56. package/dist/src/events.js +24 -0
  57. package/dist/src/events.js.map +1 -0
  58. package/dist/src/forward.d.ts +51 -0
  59. package/dist/src/forward.js +170 -0
  60. package/dist/src/forward.js.map +1 -0
  61. package/dist/src/fs-scope.d.ts +17 -0
  62. package/dist/src/fs-scope.js +47 -0
  63. package/dist/src/fs-scope.js.map +1 -0
  64. package/dist/src/github.d.ts +70 -0
  65. package/dist/src/github.js +178 -0
  66. package/dist/src/github.js.map +1 -0
  67. package/dist/src/gitops.d.ts +113 -0
  68. package/dist/src/gitops.js +557 -0
  69. package/dist/src/gitops.js.map +1 -0
  70. package/dist/src/hub.d.ts +50 -0
  71. package/dist/src/hub.js +92 -0
  72. package/dist/src/hub.js.map +1 -0
  73. package/dist/src/index.d.ts +22 -0
  74. package/dist/src/index.js +56 -0
  75. package/dist/src/index.js.map +1 -0
  76. package/dist/src/jobs/scheduler.d.ts +94 -0
  77. package/dist/src/jobs/scheduler.js +373 -0
  78. package/dist/src/jobs/scheduler.js.map +1 -0
  79. package/dist/src/jobs/store.d.ts +33 -0
  80. package/dist/src/jobs/store.js +111 -0
  81. package/dist/src/jobs/store.js.map +1 -0
  82. package/dist/src/log.d.ts +61 -0
  83. package/dist/src/log.js +166 -0
  84. package/dist/src/log.js.map +1 -0
  85. package/dist/src/migrate-state-dir.d.ts +1 -0
  86. package/dist/src/migrate-state-dir.js +47 -0
  87. package/dist/src/migrate-state-dir.js.map +1 -0
  88. package/dist/src/models.d.ts +36 -0
  89. package/dist/src/models.js +71 -0
  90. package/dist/src/models.js.map +1 -0
  91. package/dist/src/permission-gate.d.ts +48 -0
  92. package/dist/src/permission-gate.js +93 -0
  93. package/dist/src/permission-gate.js.map +1 -0
  94. package/dist/src/permission-scope.d.ts +77 -0
  95. package/dist/src/permission-scope.js +244 -0
  96. package/dist/src/permission-scope.js.map +1 -0
  97. package/dist/src/ports.d.ts +71 -0
  98. package/dist/src/ports.js +216 -0
  99. package/dist/src/ports.js.map +1 -0
  100. package/dist/src/projects.d.ts +83 -0
  101. package/dist/src/projects.js +205 -0
  102. package/dist/src/projects.js.map +1 -0
  103. package/dist/src/protocol.d.ts +1226 -0
  104. package/dist/src/protocol.js +16 -0
  105. package/dist/src/protocol.js.map +1 -0
  106. package/dist/src/repo-sync.d.ts +49 -0
  107. package/dist/src/repo-sync.js +83 -0
  108. package/dist/src/repo-sync.js.map +1 -0
  109. package/dist/src/server.d.ts +33 -0
  110. package/dist/src/server.js +973 -0
  111. package/dist/src/server.js.map +1 -0
  112. package/dist/src/terminal.d.ts +32 -0
  113. package/dist/src/terminal.js +92 -0
  114. package/dist/src/terminal.js.map +1 -0
  115. package/dist/src/titler.d.ts +15 -0
  116. package/dist/src/titler.js +72 -0
  117. package/dist/src/titler.js.map +1 -0
  118. package/dist/src/types.d.ts +99 -0
  119. package/dist/src/types.js +3 -0
  120. package/dist/src/types.js.map +1 -0
  121. package/dist/src/usage-limit.d.ts +49 -0
  122. package/dist/src/usage-limit.js +83 -0
  123. package/dist/src/usage-limit.js.map +1 -0
  124. package/dist/src/usage.d.ts +23 -0
  125. package/dist/src/usage.js +63 -0
  126. package/dist/src/usage.js.map +1 -0
  127. package/dist/src/workspace.d.ts +303 -0
  128. package/dist/src/workspace.js +1086 -0
  129. package/dist/src/workspace.js.map +1 -0
  130. package/dist/src/worktree.d.ts +133 -0
  131. package/dist/src/worktree.js +561 -0
  132. package/dist/src/worktree.js.map +1 -0
  133. 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>;