@nyte-ai/host 0.0.0-stage → 0.0.18

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 (235) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +6 -2
  3. package/THIRD-PARTY-NOTICES.md +800 -0
  4. package/dist/chunks/canvas-preview-0cmbkp2j.js +65 -0
  5. package/dist/chunks/canvas-preview-0nq75h9k.js +7 -0
  6. package/dist/chunks/canvas-preview-0nrnbt76.js +497 -0
  7. package/dist/chunks/canvas-preview-1sq7z9jq.js +17 -0
  8. package/dist/chunks/canvas-preview-1ta3avah.js +56 -0
  9. package/dist/chunks/canvas-preview-2zdyh9ny.js +26 -0
  10. package/dist/chunks/canvas-preview-31w7xm8z.js +34 -0
  11. package/dist/chunks/canvas-preview-4b6sayhg.js +295 -0
  12. package/dist/chunks/canvas-preview-4e0pxa32.js +63 -0
  13. package/dist/chunks/canvas-preview-518dh8by.js +169 -0
  14. package/dist/chunks/canvas-preview-5hxat7hh.js +239 -0
  15. package/dist/chunks/canvas-preview-5mex725c.js +14 -0
  16. package/dist/chunks/canvas-preview-5z63am63.js +295 -0
  17. package/dist/chunks/canvas-preview-65xqjw7f.js +20 -0
  18. package/dist/chunks/canvas-preview-69fkk9yn.js +95 -0
  19. package/dist/chunks/canvas-preview-75db60xy.js +457 -0
  20. package/dist/chunks/canvas-preview-76fwvd6e.js +272 -0
  21. package/dist/chunks/canvas-preview-8xgt67ka.js +598 -0
  22. package/dist/chunks/canvas-preview-98aj5p34.js +176 -0
  23. package/dist/chunks/canvas-preview-9aqczacs.js +73 -0
  24. package/dist/chunks/canvas-preview-a3yw0j70.js +72 -0
  25. package/dist/chunks/canvas-preview-azg56359.js +68 -0
  26. package/dist/chunks/canvas-preview-d9wwhbtz.js +240 -0
  27. package/dist/chunks/canvas-preview-ehf3vp31.js +411 -0
  28. package/dist/chunks/canvas-preview-evh92ywd.js +369 -0
  29. package/dist/chunks/canvas-preview-ewgspmsd.js +81 -0
  30. package/dist/chunks/canvas-preview-g3qj3y3k.js +156 -0
  31. package/dist/chunks/canvas-preview-h8hshnff.js +63 -0
  32. package/dist/chunks/canvas-preview-j1tnf51w.js +36 -0
  33. package/dist/chunks/canvas-preview-kdqgrstc.js +194 -0
  34. package/dist/chunks/canvas-preview-kn7kvbfj.js +12 -0
  35. package/dist/chunks/canvas-preview-m02v4yy6.js +386 -0
  36. package/dist/chunks/canvas-preview-mgcx2b2p.js +271 -0
  37. package/dist/chunks/canvas-preview-rp4x6y1h.js +144 -0
  38. package/dist/chunks/canvas-preview-rp6fz0w5.js +130 -0
  39. package/dist/chunks/canvas-preview-s94ebwf5.js +112 -0
  40. package/dist/chunks/canvas-preview-senpjwep.js +518 -0
  41. package/dist/chunks/canvas-preview-skzwvw4d.js +23 -0
  42. package/dist/chunks/canvas-preview-srgfpdmf.js +60 -0
  43. package/dist/chunks/canvas-preview-tjhabynd.js +252 -0
  44. package/dist/chunks/canvas-preview-vaatfznm.js +189 -0
  45. package/dist/chunks/canvas-preview-vax9ne4e.js +341 -0
  46. package/dist/chunks/canvas-preview-wg80rbc2.js +46 -0
  47. package/dist/chunks/canvas-preview-xn10d4f8.js +608 -0
  48. package/dist/chunks/canvas-preview-yjz0f7n4.js +50 -0
  49. package/dist/chunks/canvas-preview-ymgz0937.js +587 -0
  50. package/dist/chunks/canvas-preview-yrfz2ak6.js +134 -0
  51. package/dist/chunks/canvas-preview-zaaj99wd.js +244 -0
  52. package/dist/chunks/canvas-preview-zn2d0k9d.js +133 -0
  53. package/dist/src/canvas-preview.d.ts +29 -0
  54. package/dist/src/canvas-preview.js +267 -0
  55. package/dist/src/credentials.d.ts +44 -0
  56. package/dist/src/credentials.js +10 -0
  57. package/dist/src/deploy/cloudflare/worker.d.ts +50 -0
  58. package/dist/src/deploy/cloudflare/worker.js +196 -0
  59. package/dist/src/deploy/vercel/nitro.config.d.ts +2 -0
  60. package/dist/src/deploy/vercel/nitro.config.js +30 -0
  61. package/dist/src/deploy/vercel/server/routes/[...].d.ts +2 -0
  62. package/dist/src/deploy/vercel/server/routes/[...].js +18 -0
  63. package/dist/src/deploy/vercel/server/utils/host.d.ts +13 -0
  64. package/dist/src/deploy/vercel/server/utils/host.js +7 -0
  65. package/dist/src/deploy/vercel/server/utils/repair.d.ts +1 -0
  66. package/dist/src/deploy/vercel/server/utils/repair.js +6 -0
  67. package/dist/src/deploy/vercel/server/utils/step.d.ts +10 -0
  68. package/dist/src/deploy/vercel/server/utils/step.js +6 -0
  69. package/dist/src/deploy/vercel/server/workflows/drive.d.ts +14 -0
  70. package/dist/src/deploy/vercel/server/workflows/drive.js +13 -0
  71. package/dist/src/durable-object.d.ts +14 -0
  72. package/dist/src/durable-object.js +231 -0
  73. package/dist/src/hash.d.ts +1 -0
  74. package/dist/src/hash.js +6 -0
  75. package/dist/src/identity-key.d.ts +11 -0
  76. package/dist/src/identity-key.js +9 -0
  77. package/dist/src/identity.d.ts +12 -0
  78. package/dist/src/identity.js +6 -0
  79. package/dist/src/index.d.ts +21 -0
  80. package/dist/src/index.js +120 -0
  81. package/dist/src/key-file.d.ts +1 -0
  82. package/dist/src/key-file.js +7 -0
  83. package/dist/src/listen-fetch.d.ts +8 -0
  84. package/dist/src/listen-fetch.js +9 -0
  85. package/dist/src/listen.d.ts +4 -0
  86. package/dist/src/listen.js +10 -0
  87. package/dist/src/local/command.d.ts +15 -0
  88. package/dist/src/local/command.js +8 -0
  89. package/dist/src/local/feed.d.ts +7 -0
  90. package/dist/src/local/feed.js +6 -0
  91. package/dist/src/local/files.d.ts +18 -0
  92. package/dist/src/local/files.js +13 -0
  93. package/dist/src/local/git-watch.d.ts +15 -0
  94. package/dist/src/local/git-watch.js +7 -0
  95. package/dist/src/local/git.d.ts +5 -0
  96. package/dist/src/local/git.js +13 -0
  97. package/dist/src/local/github.d.ts +30 -0
  98. package/dist/src/local/github.js +9 -0
  99. package/dist/src/local/identity.d.ts +3 -0
  100. package/dist/src/local/identity.js +7 -0
  101. package/dist/src/local/jobs.d.ts +7 -0
  102. package/dist/src/local/jobs.js +6 -0
  103. package/dist/src/local/legacy-trust.d.ts +10 -0
  104. package/dist/src/local/legacy-trust.js +6 -0
  105. package/dist/src/local/patch.d.ts +16 -0
  106. package/dist/src/local/patch.js +17 -0
  107. package/dist/src/local/provider.d.ts +11 -0
  108. package/dist/src/local/provider.js +20 -0
  109. package/dist/src/local/snapshots.d.ts +7 -0
  110. package/dist/src/local/snapshots.js +11 -0
  111. package/dist/src/local/text.d.ts +1 -0
  112. package/dist/src/local/text.js +6 -0
  113. package/dist/src/local/tree.d.ts +50 -0
  114. package/dist/src/local/tree.js +16 -0
  115. package/dist/src/local/workspace-migration.d.ts +2 -0
  116. package/dist/src/local/workspace-migration.js +7 -0
  117. package/dist/src/local/worktrees.d.ts +46 -0
  118. package/dist/src/local/worktrees.js +14 -0
  119. package/dist/src/mcp/config.d.ts +75 -0
  120. package/dist/src/mcp/config.js +12 -0
  121. package/dist/src/mcp/connect.d.ts +28 -0
  122. package/dist/src/mcp/connect.js +9 -0
  123. package/dist/src/mcp/hub.d.ts +19 -0
  124. package/dist/src/mcp/hub.js +11 -0
  125. package/dist/src/mcp/oauth.d.ts +46 -0
  126. package/dist/src/mcp/oauth.js +12 -0
  127. package/dist/src/mcp/tools.d.ts +29 -0
  128. package/dist/src/mcp/tools.js +12 -0
  129. package/dist/src/open.d.ts +42 -0
  130. package/dist/src/open.js +44 -0
  131. package/dist/src/plugins/loader.d.ts +21 -0
  132. package/dist/src/plugins/loader.js +11 -0
  133. package/dist/src/postgres.d.ts +19 -0
  134. package/dist/src/postgres.js +8 -0
  135. package/dist/src/providers.d.ts +16 -0
  136. package/dist/src/providers.js +112 -0
  137. package/dist/src/secrets.d.ts +12 -0
  138. package/dist/src/secrets.js +8 -0
  139. package/dist/src/serve/binding.d.ts +39 -0
  140. package/dist/src/serve/binding.js +6 -0
  141. package/dist/src/serve/handler.d.ts +15 -0
  142. package/dist/src/serve/handler.js +8 -0
  143. package/dist/src/serve/stream-server.d.ts +6 -0
  144. package/dist/src/serve/stream-server.js +6 -0
  145. package/dist/src/session-index.d.ts +11 -0
  146. package/dist/src/session-index.js +11 -0
  147. package/dist/src/shell-env.d.ts +14 -0
  148. package/dist/src/shell-env.js +108 -0
  149. package/dist/src/sqlite-workers.d.ts +6 -0
  150. package/dist/src/sqlite-workers.js +6 -0
  151. package/dist/src/sqlite.d.ts +7 -0
  152. package/dist/src/sqlite.js +10 -0
  153. package/dist/src/store-owner.d.ts +15 -0
  154. package/dist/src/store-owner.js +9 -0
  155. package/dist/src/store-rows.d.ts +13 -0
  156. package/dist/src/store-rows.js +26 -0
  157. package/dist/src/store-usage.d.ts +25 -0
  158. package/dist/src/store-usage.js +16 -0
  159. package/dist/src/usage-scan.d.ts +24 -0
  160. package/dist/src/usage-scan.js +65 -0
  161. package/dist/src/usage-service.d.ts +22 -0
  162. package/dist/src/usage-service.js +12 -0
  163. package/dist/src/usage-summary.d.ts +9 -0
  164. package/dist/src/usage-summary.js +16 -0
  165. package/dist/src/usage-types.d.ts +86 -0
  166. package/dist/src/usage-types.js +0 -0
  167. package/dist/src/usage-worker.d.ts +1 -0
  168. package/dist/src/usage-worker.js +25 -0
  169. package/dist/src/usage.d.ts +72 -0
  170. package/dist/src/usage.js +13 -0
  171. package/package.json +132 -3
  172. package/src/canvas-preview.ts +402 -0
  173. package/src/credentials.ts +294 -0
  174. package/src/deploy/cloudflare/README.md +3 -0
  175. package/src/deploy/cloudflare/worker.ts +306 -0
  176. package/src/deploy/cloudflare/wrangler.jsonc +12 -0
  177. package/src/deploy/vercel/README.md +3 -0
  178. package/src/deploy/vercel/nitro.config.ts +29 -0
  179. package/src/deploy/vercel/server/routes/[...].ts +10 -0
  180. package/src/deploy/vercel/server/utils/host.ts +104 -0
  181. package/src/deploy/vercel/server/utils/repair.ts +35 -0
  182. package/src/deploy/vercel/server/utils/step.ts +25 -0
  183. package/src/deploy/vercel/server/workflows/drive.ts +46 -0
  184. package/src/deploy/vercel/tsconfig.json +9 -0
  185. package/src/deploy/vercel/types/bun.d.ts +2 -0
  186. package/src/durable-object.ts +386 -0
  187. package/src/hash.ts +5 -0
  188. package/src/identity-key.ts +20 -0
  189. package/src/identity.ts +66 -0
  190. package/src/index.ts +21 -0
  191. package/src/key-file.ts +53 -0
  192. package/src/listen-fetch.ts +409 -0
  193. package/src/listen.ts +228 -0
  194. package/src/local/command.ts +109 -0
  195. package/src/local/feed.ts +70 -0
  196. package/src/local/files.ts +812 -0
  197. package/src/local/git-watch.ts +189 -0
  198. package/src/local/git.ts +914 -0
  199. package/src/local/github.ts +692 -0
  200. package/src/local/identity.ts +21 -0
  201. package/src/local/jobs.ts +587 -0
  202. package/src/local/legacy-trust.ts +105 -0
  203. package/src/local/patch.ts +334 -0
  204. package/src/local/provider.ts +184 -0
  205. package/src/local/snapshots.ts +776 -0
  206. package/src/local/text.ts +9 -0
  207. package/src/local/tree.ts +398 -0
  208. package/src/local/workspace-migration.ts +95 -0
  209. package/src/local/worktrees.ts +239 -0
  210. package/src/mcp/config.ts +330 -0
  211. package/src/mcp/connect.ts +105 -0
  212. package/src/mcp/hub.ts +836 -0
  213. package/src/mcp/oauth.ts +436 -0
  214. package/src/mcp/tools.ts +333 -0
  215. package/src/open.ts +469 -0
  216. package/src/plugins/loader.ts +186 -0
  217. package/src/postgres.ts +492 -0
  218. package/src/providers.ts +135 -0
  219. package/src/secrets.ts +31 -0
  220. package/src/serve/binding.ts +628 -0
  221. package/src/serve/handler.ts +362 -0
  222. package/src/serve/stream-server.ts +176 -0
  223. package/src/session-index.ts +99 -0
  224. package/src/shell-env.ts +153 -0
  225. package/src/sqlite-workers.ts +283 -0
  226. package/src/sqlite.ts +528 -0
  227. package/src/store-owner.ts +98 -0
  228. package/src/store-rows.ts +110 -0
  229. package/src/store-usage.ts +344 -0
  230. package/src/usage-scan.ts +81 -0
  231. package/src/usage-service.ts +73 -0
  232. package/src/usage-summary.ts +79 -0
  233. package/src/usage-types.ts +87 -0
  234. package/src/usage-worker.ts +24 -0
  235. package/src/usage.ts +701 -0
@@ -0,0 +1,457 @@
1
+ import {
2
+ run2,
3
+ findExecutable2
4
+ } from "./canvas-preview-azg56359.js";
5
+
6
+ // src/local/github.ts
7
+ import { spawn } from "node:child_process";
8
+ import { homedir } from "node:os";
9
+ import { Type } from "typebox";
10
+ import { Compile } from "typebox/compile";
11
+ import { dev } from "@nyte-ai/core";
12
+ var ENV = {
13
+ GH_PROMPT_DISABLED: "1",
14
+ GH_NO_UPDATE_NOTIFIER: "1",
15
+ GIT_TERMINAL_PROMPT: "0",
16
+ NO_COLOR: "1",
17
+ LC_ALL: "C"
18
+ };
19
+ var OUTPUT_LIMIT = 1e6;
20
+ var QUERY_TIMEOUT_MS = 1e4;
21
+ var CREATE_TIMEOUT_MS = 60000;
22
+ var SIGN_IN_CODE_TIMEOUT_MS = 30000;
23
+ var SIGN_IN_LIFETIME_MS = 15 * 60000;
24
+ var NO_PULL_REQUEST = { kind: "none" };
25
+ var PULL_REQUEST_FIELDS = "number,title,url,state,isDraft,headRefName,baseRefName,statusCheckRollup";
26
+ var REMOTE_PRIORITY = ["upstream", "github", "origin"];
27
+ var RECOVERY = {
28
+ update: "Update the GitHub CLI (gh), then try again.",
29
+ signIn: "GitHub rejected the CLI's login. Run gh auth login in a terminal, then try again.",
30
+ signOut: "Couldn't sign out of GitHub. Run gh auth logout in a terminal, then try again.",
31
+ account: "Couldn't reach GitHub. Try again.",
32
+ pullRequest: "Couldn't read this branch's pull request. Try again.",
33
+ createPullRequest: "Couldn't open a pull request. Run gh pr create in a terminal to see why."
34
+ };
35
+ var authSchema = Compile(Type.Array(Type.Object({ active: Type.Boolean(), state: Type.String(), login: Type.String() })));
36
+ var accountSchema = Compile(Type.Object({
37
+ login: Type.String({ minLength: 1 }),
38
+ name: Type.Union([Type.String(), Type.Null()]),
39
+ avatar_url: Type.Union([Type.String(), Type.Null()])
40
+ }));
41
+ var optionalText = Type.Optional(Type.Union([Type.String(), Type.Null()]));
42
+ var PullRequestJson = Type.Object({
43
+ number: Type.Integer({ minimum: 1, maximum: Number.MAX_SAFE_INTEGER }),
44
+ title: Type.String(),
45
+ url: Type.String(),
46
+ state: Type.Enum(["OPEN", "CLOSED", "MERGED"]),
47
+ isDraft: Type.Boolean(),
48
+ headRefName: Type.String({ minLength: 1 }),
49
+ baseRefName: Type.String({ minLength: 1 }),
50
+ statusCheckRollup: Type.Union([
51
+ Type.Null(),
52
+ Type.Array(Type.Object({
53
+ __typename: Type.String(),
54
+ name: optionalText,
55
+ context: optionalText,
56
+ status: optionalText,
57
+ conclusion: optionalText,
58
+ state: optionalText,
59
+ detailsUrl: optionalText,
60
+ targetUrl: optionalText
61
+ }))
62
+ ])
63
+ });
64
+ var pullRequestSchema = Compile(PullRequestJson);
65
+ function parseJson(validator, text) {
66
+ try {
67
+ return validator.Parse(JSON.parse(text));
68
+ } catch {
69
+ return;
70
+ }
71
+ }
72
+ function safeUrl(value, hostnames) {
73
+ const url = URL.parse(value ?? "");
74
+ if (url === null || url.protocol !== "https:" || url.username !== "" || url.password !== "" || url.port !== "" || hostnames !== undefined && !hostnames.includes(url.hostname))
75
+ return;
76
+ return url.href;
77
+ }
78
+ var REPOSITORY_PART = /^[A-Za-z0-9](?:[A-Za-z0-9._-]*[A-Za-z0-9])?$/u;
79
+ function parseRemote(remoteName, remote) {
80
+ const scp = /^(?:[^@\s]+@)?github\.com:([^/\s]+)\/([^/\s]+?)\/?$/iu.exec(remote);
81
+ const url = scp === null ? URL.parse(remote) : null;
82
+ const parts = scp === null ? url !== null && url.hostname.toLowerCase() === "github.com" ? url.pathname.split("/").filter((segment) => segment !== "") : [] : [scp[1] ?? "", scp[2] ?? ""];
83
+ if (parts.length !== 2)
84
+ return;
85
+ const owner = parts[0] ?? "";
86
+ const name = (parts[1] ?? "").replace(/\.git$/iu, "");
87
+ if (!REPOSITORY_PART.test(owner) || !REPOSITORY_PART.test(name))
88
+ return;
89
+ return { owner, name, remoteName, url: `https://github.com/${owner}/${name}` };
90
+ }
91
+ function checkState(entry) {
92
+ if (entry.__typename === "StatusContext") {
93
+ if (entry.state === "SUCCESS")
94
+ return "passed";
95
+ return entry.state === "ERROR" || entry.state === "FAILURE" ? "failed" : "pending";
96
+ }
97
+ if (entry.status !== "COMPLETED")
98
+ return "pending";
99
+ switch (entry.conclusion) {
100
+ case "SUCCESS":
101
+ case "NEUTRAL":
102
+ return "passed";
103
+ case "SKIPPED":
104
+ case "STALE":
105
+ return "skipped";
106
+ default:
107
+ return "failed";
108
+ }
109
+ }
110
+ function readCheck(entry) {
111
+ const url = safeUrl(entry.detailsUrl ?? entry.targetUrl);
112
+ const check = { name: entry.name ?? entry.context ?? "Check", state: checkState(entry) };
113
+ return url === undefined ? check : { ...check, url };
114
+ }
115
+ function readPullRequestJson(text) {
116
+ const pull = parseJson(pullRequestSchema, text);
117
+ const url = safeUrl(pull?.url, ["github.com"]);
118
+ if (pull === undefined || url === undefined)
119
+ return;
120
+ return {
121
+ number: pull.number,
122
+ title: pull.title,
123
+ url,
124
+ state: pull.state,
125
+ draft: pull.isDraft,
126
+ headRefName: pull.headRefName,
127
+ baseRefName: pull.baseRefName,
128
+ checks: (pull.statusCheckRollup ?? []).map(readCheck)
129
+ };
130
+ }
131
+ function readAccountJson(text) {
132
+ const account = parseJson(accountSchema, text);
133
+ if (account === undefined)
134
+ return;
135
+ const avatarUrl = safeUrl(account.avatar_url, ["avatars.githubusercontent.com"]);
136
+ return {
137
+ login: account.login,
138
+ ...account.name === null || account.name === "" ? {} : { name: account.name },
139
+ ...avatarUrl === undefined ? {} : { avatarUrl }
140
+ };
141
+ }
142
+ var USER_CODE = /one-time code\W*([A-Z0-9]{4}-[A-Z0-9]{4})\b/iu;
143
+ var PRINTED_URL = /https:\/\/\S+/u;
144
+ var SIGN_IN_LINE_LIMIT = 4096;
145
+ function startSignIn(file, cwd, ended) {
146
+ const started = Promise.withResolvers();
147
+ const expiresAt = Date.now() + SIGN_IN_LIFETIME_MS;
148
+ let userCode;
149
+ let verificationUri;
150
+ let done = false;
151
+ const child = spawn(file, [
152
+ "auth",
153
+ "login",
154
+ "--hostname",
155
+ "github.com",
156
+ "--web",
157
+ "--git-protocol",
158
+ "https",
159
+ "--skip-ssh-key"
160
+ ], { cwd, env: { ...process.env, ...ENV }, stdio: ["ignore", "pipe", "pipe"] });
161
+ const end = (start) => {
162
+ if (done)
163
+ return;
164
+ done = true;
165
+ clearTimeout(codeTimer);
166
+ clearTimeout(lifetime);
167
+ child.stdout?.destroy();
168
+ child.stderr?.destroy();
169
+ if (child.exitCode === null && child.signalCode === null)
170
+ child.kill("SIGKILL");
171
+ started.resolve(start);
172
+ ended();
173
+ };
174
+ const readLine = (line) => {
175
+ userCode ??= USER_CODE.exec(line)?.[1]?.toUpperCase();
176
+ const printed = PRINTED_URL.exec(line)?.[0];
177
+ if (verificationUri === undefined && printed !== undefined) {
178
+ verificationUri = safeUrl(printed, ["github.com"]);
179
+ if (verificationUri === undefined)
180
+ end({ kind: "failed" });
181
+ }
182
+ if (userCode === undefined || verificationUri === undefined)
183
+ return;
184
+ clearTimeout(codeTimer);
185
+ started.resolve({ kind: "code", deviceCode: { userCode, verificationUri } });
186
+ };
187
+ for (const stream of [child.stdout, child.stderr]) {
188
+ let pending = "";
189
+ stream?.setEncoding("utf8");
190
+ stream?.on("data", (chunk) => {
191
+ const lines = (pending + chunk).split(/\r?\n/u);
192
+ pending = (lines.pop() ?? "").slice(-SIGN_IN_LINE_LIMIT);
193
+ for (const line of lines)
194
+ if (!done)
195
+ readLine(line);
196
+ });
197
+ }
198
+ child.on("error", () => end({ kind: "failed" }));
199
+ child.on("close", (code) => end(code === 0 ? { kind: "ended" } : { kind: "failed" }));
200
+ const codeTimer = setTimeout(() => end({ kind: "failed" }), SIGN_IN_CODE_TIMEOUT_MS);
201
+ const lifetime = setTimeout(() => end({ kind: "failed" }), SIGN_IN_LIFETIME_MS);
202
+ return { started: started.promise, expiresAt, cancel: () => end({ kind: "ended" }) };
203
+ }
204
+ function ghCommand(binary) {
205
+ return async (cwd, args, extra) => {
206
+ const file = await findExecutable2(binary);
207
+ if (file === null)
208
+ return { kind: "missing" };
209
+ const started = Date.now();
210
+ const ran = await run2(file, args, {
211
+ cwd,
212
+ env: ENV,
213
+ input: extra?.input,
214
+ limit: OUTPUT_LIMIT,
215
+ timeoutMs: extra?.timeoutMs ?? QUERY_TIMEOUT_MS
216
+ }).catch(() => null);
217
+ dev("github", "run", {
218
+ command: args.slice(0, 2).join(" "),
219
+ code: ran?.code ?? null,
220
+ ms: Date.now() - started
221
+ });
222
+ if (ran === null || ran.code === null || ran.truncated)
223
+ return { kind: "failed" };
224
+ return {
225
+ kind: "completed",
226
+ code: ran.code,
227
+ stdout: ran.stdout.toString("utf8"),
228
+ stderr: ran.stderr
229
+ };
230
+ };
231
+ }
232
+ async function readAuth(gh, cwd) {
233
+ const result = await gh(cwd, [
234
+ "auth",
235
+ "status",
236
+ "--hostname",
237
+ "github.com",
238
+ "--json",
239
+ "hosts",
240
+ "--jq",
241
+ '[(.hosts["github.com"] // [])[] | {active, state, login}]'
242
+ ]);
243
+ if (result.kind === "missing")
244
+ return result;
245
+ if (result.kind === "failed")
246
+ return { kind: "error", message: RECOVERY.account };
247
+ if (result.code !== 0)
248
+ return {
249
+ kind: "error",
250
+ message: /unknown flag: --(?:json|jq)\b/u.test(result.stderr) ? RECOVERY.update : RECOVERY.account
251
+ };
252
+ const entries = parseJson(authSchema, result.stdout);
253
+ if (entries === undefined)
254
+ return { kind: "error", message: RECOVERY.update };
255
+ const active = entries.find((entry) => entry.active);
256
+ if (active === undefined)
257
+ return { kind: "signed_out" };
258
+ if (active.state !== "success")
259
+ return {
260
+ kind: "error",
261
+ message: active.state === "error" ? RECOVERY.signIn : RECOVERY.account
262
+ };
263
+ return { kind: "ready", login: active.login };
264
+ }
265
+ async function readAccountState(gh, cwd) {
266
+ const auth = await readAuth(gh, cwd);
267
+ if (auth.kind === "missing")
268
+ return { kind: "cli_missing" };
269
+ if (auth.kind !== "ready")
270
+ return auth;
271
+ const result = await gh(cwd, ["api", "--hostname", "github.com", "user"]);
272
+ const account = result.kind === "completed" && result.code === 0 ? readAccountJson(result.stdout) : undefined;
273
+ return account === undefined ? { kind: "error", message: RECOVERY.account } : { kind: "ready", account };
274
+ }
275
+ function localGitHubAccount2(options) {
276
+ const binary = options?.gh ?? "gh";
277
+ const gh = ghCommand(binary);
278
+ const home = options?.home ?? homedir();
279
+ let signing;
280
+ const signingState = async (attempt) => {
281
+ const start = await attempt.started;
282
+ if (start.kind !== "code") {
283
+ const state = await readAccountState(gh, home);
284
+ return start.kind === "failed" && state.kind === "signed_out" ? { kind: "error", message: RECOVERY.signIn } : state;
285
+ }
286
+ return {
287
+ kind: "signing_in",
288
+ deviceCode: {
289
+ ...start.deviceCode,
290
+ expiresInSeconds: Math.max(0, Math.ceil((attempt.expiresAt - Date.now()) / 1000))
291
+ }
292
+ };
293
+ };
294
+ return {
295
+ account: () => signing === undefined ? readAccountState(gh, home) : signingState(signing),
296
+ async signIn() {
297
+ if (signing !== undefined)
298
+ return signingState(signing);
299
+ const state = await readAccountState(gh, home);
300
+ if (state.kind !== "signed_out" && state.kind !== "error")
301
+ return state;
302
+ if (signing !== undefined)
303
+ return signingState(signing);
304
+ const file = await findExecutable2(binary);
305
+ if (file === null)
306
+ return { kind: "cli_missing" };
307
+ const attempt = startSignIn(file, home, () => {
308
+ if (signing === attempt)
309
+ signing = undefined;
310
+ });
311
+ signing = attempt;
312
+ return signingState(attempt);
313
+ },
314
+ async signOut() {
315
+ if (signing !== undefined) {
316
+ signing.cancel();
317
+ signing = undefined;
318
+ return readAccountState(gh, home);
319
+ }
320
+ const auth = await readAuth(gh, home);
321
+ if (auth.kind !== "ready")
322
+ return readAccountState(gh, home);
323
+ const result = await gh(home, [
324
+ "auth",
325
+ "logout",
326
+ "--hostname",
327
+ "github.com",
328
+ "--user",
329
+ auth.login
330
+ ]);
331
+ const state = await readAccountState(gh, home);
332
+ if (result.kind === "completed" && result.code === 0 || state.kind !== "ready")
333
+ return state;
334
+ return { kind: "error", message: RECOVERY.signOut };
335
+ }
336
+ };
337
+ }
338
+ function localGitHub2(options) {
339
+ const gh = ghCommand(options?.gh ?? "gh");
340
+ const gitBinary = options?.git ?? "git";
341
+ const git = async (cwd, args) => {
342
+ const ran = await run2(gitBinary, args, {
343
+ cwd,
344
+ env: ENV,
345
+ timeoutMs: QUERY_TIMEOUT_MS
346
+ }).catch(() => null);
347
+ return ran?.code === 0 ? ran.stdout.toString("utf8").trim() : null;
348
+ };
349
+ const remotes = async (cwd) => {
350
+ const listed = await git(cwd, ["remote", "-v"]) ?? "";
351
+ const found = new Map;
352
+ for (const line of listed.split(`
353
+ `)) {
354
+ const [name = "", url = ""] = line.split(/\s+/u);
355
+ const repository = found.has(name) ? undefined : parseRemote(name, url);
356
+ if (repository !== undefined)
357
+ found.set(name, repository);
358
+ }
359
+ const rank = (name) => {
360
+ const position = REMOTE_PRIORITY.findIndex((candidate) => candidate === name);
361
+ return position < 0 ? REMOTE_PRIORITY.length : position;
362
+ };
363
+ return [...found.values()].sort((left, right) => rank(left.remoteName) - rank(right.remoteName));
364
+ };
365
+ const readHead = async (cwd, repository, found) => {
366
+ const branch = await git(cwd, ["symbolic-ref", "--quiet", "--short", "HEAD"]);
367
+ if (branch === null || branch === "")
368
+ return;
369
+ const tracked = await git(cwd, ["config", "--get", `branch.${branch}.remote`]);
370
+ const owner = found.find((candidate) => candidate.remoteName === tracked)?.owner;
371
+ return owner === undefined || owner === repository.owner ? branch : `${owner}:${branch}`;
372
+ };
373
+ const readPullRequest = async (cwd, repository, head) => {
374
+ if (head === undefined)
375
+ return { kind: "none" };
376
+ const result = await gh(cwd, [
377
+ "pr",
378
+ "view",
379
+ head,
380
+ "--repo",
381
+ `${repository.owner}/${repository.name}`,
382
+ "--json",
383
+ PULL_REQUEST_FIELDS
384
+ ]);
385
+ if (result.kind === "completed" && result.code === 0) {
386
+ const pullRequest = readPullRequestJson(result.stdout);
387
+ return pullRequest === undefined ? { kind: "error", message: RECOVERY.pullRequest } : { kind: "ready", pullRequest };
388
+ }
389
+ if (result.kind === "completed" && /no (?:open )?pull requests? found/iu.test(result.stderr))
390
+ return { kind: "none" };
391
+ return { kind: "error", message: RECOVERY.pullRequest };
392
+ };
393
+ const readState = async (cwd) => {
394
+ const [found, auth] = await Promise.all([remotes(cwd), readAuth(gh, cwd)]);
395
+ const repository = found[0];
396
+ const located = repository === undefined ? {} : { repository };
397
+ if (auth.kind !== "ready")
398
+ return { state: { ...located, pullRequest: { kind: "unavailable" } }, auth, head: undefined };
399
+ if (repository === undefined)
400
+ return { state: { pullRequest: NO_PULL_REQUEST }, auth, head: undefined };
401
+ const head = await readHead(cwd, repository, found);
402
+ return {
403
+ state: { repository, pullRequest: await readPullRequest(cwd, repository, head) },
404
+ auth,
405
+ head
406
+ };
407
+ };
408
+ const createPullRequest = async (cwd, input) => {
409
+ const { state, auth, head } = await readState(cwd);
410
+ if (auth.kind === "missing")
411
+ return { kind: "cli_missing" };
412
+ if (auth.kind === "signed_out")
413
+ return { kind: "signed_out" };
414
+ if (auth.kind === "error")
415
+ return { kind: "failed", message: auth.message };
416
+ const { repository, pullRequest } = state;
417
+ if (repository === undefined)
418
+ return { kind: "no_remote" };
419
+ if (head === undefined)
420
+ return { kind: "detached" };
421
+ if (pullRequest.kind === "ready" && pullRequest.pullRequest.state === "OPEN")
422
+ return { kind: "exists", pullRequest: pullRequest.pullRequest };
423
+ const title = input.title?.trim() ?? "";
424
+ const body = input.body ?? "";
425
+ const result = await gh(cwd, [
426
+ "pr",
427
+ "create",
428
+ "--repo",
429
+ `${repository.owner}/${repository.name}`,
430
+ "--head",
431
+ head,
432
+ ...title === "" ? [] : ["--title", title],
433
+ ...body === "" ? [] : ["--body-file", "-"],
434
+ ...title === "" || body === "" ? ["--fill"] : [],
435
+ ...input.draft === true ? ["--draft"] : []
436
+ ], { input: body, timeoutMs: CREATE_TIMEOUT_MS });
437
+ if (result.kind === "missing")
438
+ return { kind: "cli_missing" };
439
+ if (result.kind === "completed" && result.code === 0) {
440
+ const url = result.stdout.split(/\r?\n/u).map((line) => safeUrl(line.trim(), ["github.com"])).find((candidate) => candidate !== undefined);
441
+ if (url !== undefined)
442
+ return { kind: "created", url };
443
+ }
444
+ if (result.kind === "completed" && /already exists/iu.test(result.stderr)) {
445
+ const current = await readPullRequest(cwd, repository, head);
446
+ if (current.kind === "ready")
447
+ return { kind: "exists", pullRequest: current.pullRequest };
448
+ }
449
+ return { kind: "failed", message: RECOVERY.createPullRequest };
450
+ };
451
+ return (env) => ({
452
+ state: async () => (await readState(env.cwd)).state,
453
+ createPullRequest: (input) => createPullRequest(env.cwd, input)
454
+ });
455
+ }
456
+
457
+ export { localGitHubAccount2, localGitHub2 };