@openagt/dashboard 0.9.0 → 0.11.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 (223) hide show
  1. package/README.md +9 -17
  2. package/dist/built-in.d.ts +45 -16
  3. package/dist/built-in.d.ts.map +1 -1
  4. package/dist/built-in.js +95 -32
  5. package/dist/built-in.js.map +1 -1
  6. package/dist/cli.d.ts +4 -10
  7. package/dist/cli.d.ts.map +1 -1
  8. package/dist/cli.js +11 -67
  9. package/dist/cli.js.map +1 -1
  10. package/dist/client.d.ts +2 -1
  11. package/dist/client.d.ts.map +1 -1
  12. package/dist/client.js +3 -4
  13. package/dist/client.js.map +1 -1
  14. package/dist/daemon-runtime.d.ts +12 -12
  15. package/dist/daemon-runtime.d.ts.map +1 -1
  16. package/dist/daemon-runtime.js +97 -37
  17. package/dist/daemon-runtime.js.map +1 -1
  18. package/dist/daemon.d.ts +3 -14
  19. package/dist/daemon.d.ts.map +1 -1
  20. package/dist/daemon.js +15 -26
  21. package/dist/daemon.js.map +1 -1
  22. package/dist/dashboard/bridge-endpoints.d.ts +5 -5
  23. package/dist/dashboard/bridge-endpoints.js +5 -5
  24. package/dist/dashboard/http.d.ts +1 -1
  25. package/dist/dashboard/http.js +1 -1
  26. package/dist/dashboard/machine-call.d.ts +10 -0
  27. package/dist/dashboard/machine-call.d.ts.map +1 -0
  28. package/dist/dashboard/machine-call.js +86 -0
  29. package/dist/dashboard/machine-call.js.map +1 -0
  30. package/dist/dashboard/relay-endpoints.d.ts +26 -17
  31. package/dist/dashboard/relay-endpoints.d.ts.map +1 -1
  32. package/dist/dashboard/relay-endpoints.js +70 -27
  33. package/dist/dashboard/relay-endpoints.js.map +1 -1
  34. package/dist/dashboard/remote-run.d.ts +77 -32
  35. package/dist/dashboard/remote-run.d.ts.map +1 -1
  36. package/dist/dashboard/remote-run.js +120 -42
  37. package/dist/dashboard/remote-run.js.map +1 -1
  38. package/dist/dashboard/rpc-serve.d.ts +19 -25
  39. package/dist/dashboard/rpc-serve.d.ts.map +1 -1
  40. package/dist/dashboard/rpc-serve.js +11 -22
  41. package/dist/dashboard/rpc-serve.js.map +1 -1
  42. package/dist/dashboard/screen.d.ts +53 -0
  43. package/dist/dashboard/screen.d.ts.map +1 -0
  44. package/dist/dashboard/screen.js +175 -0
  45. package/dist/dashboard/screen.js.map +1 -0
  46. package/dist/dashboard/server.d.ts +18 -19
  47. package/dist/dashboard/server.d.ts.map +1 -1
  48. package/dist/dashboard/server.js +52 -81
  49. package/dist/dashboard/server.js.map +1 -1
  50. package/dist/dashboard/start-branch.d.ts +32 -0
  51. package/dist/dashboard/start-branch.d.ts.map +1 -0
  52. package/dist/dashboard/start-branch.js +47 -0
  53. package/dist/dashboard/start-branch.js.map +1 -0
  54. package/dist/dashboard/types.d.ts +6 -14
  55. package/dist/dashboard/types.d.ts.map +1 -1
  56. package/dist/dashboard/web-start-endpoints.d.ts +2 -2
  57. package/dist/dashboard/web-start-endpoints.js +1 -1
  58. package/dist/dashboard-bundle/assets/main-9Xb8Ao4p.css +2 -0
  59. package/dist/dashboard-bundle/assets/main-DTyyQ0jM.js +140 -0
  60. package/dist/dashboard-bundle/assets/{module-v213KWfH.js → module-DKd-4BTU.js} +4 -4
  61. package/dist/dashboard-bundle/host/module.js +1 -1
  62. package/dist/dashboard-bundle/index.html +3 -3
  63. package/dist/dashboard-rpc/context.d.ts +4 -4
  64. package/dist/dashboard-rpc/context.js +5 -5
  65. package/dist/dashboard-rpc/context.js.map +1 -1
  66. package/dist/dashboard-rpc/control.d.ts +1 -1
  67. package/dist/dashboard-rpc/control.js +7 -7
  68. package/dist/dashboard-rpc/control.js.map +1 -1
  69. package/dist/dashboard-rpc/events.d.ts +1 -1
  70. package/dist/dashboard-rpc/events.js +1 -1
  71. package/dist/dashboard-rpc/index.d.ts +2 -1
  72. package/dist/dashboard-rpc/index.d.ts.map +1 -1
  73. package/dist/dashboard-rpc/index.js +5 -3
  74. package/dist/dashboard-rpc/index.js.map +1 -1
  75. package/dist/dashboard-rpc/machines.d.ts +52 -0
  76. package/dist/dashboard-rpc/machines.d.ts.map +1 -0
  77. package/dist/dashboard-rpc/machines.js +82 -0
  78. package/dist/dashboard-rpc/machines.js.map +1 -0
  79. package/dist/dashboard-rpc/modules.d.ts +1 -1
  80. package/dist/dashboard-rpc/modules.js +2 -2
  81. package/dist/dashboard-rpc/modules.js.map +1 -1
  82. package/dist/dashboard-rpc/projects.d.ts +2 -0
  83. package/dist/dashboard-rpc/projects.d.ts.map +1 -1
  84. package/dist/dashboard-rpc/projects.js +10 -2
  85. package/dist/dashboard-rpc/projects.js.map +1 -1
  86. package/dist/dashboard-rpc/reads.d.ts +3 -4
  87. package/dist/dashboard-rpc/reads.d.ts.map +1 -1
  88. package/dist/dashboard-rpc/reads.js +5 -6
  89. package/dist/dashboard-rpc/reads.js.map +1 -1
  90. package/dist/dashboard-rpc/relay-agent.d.ts +3 -3
  91. package/dist/dashboard-rpc/relay-agent.js +3 -3
  92. package/dist/dashboard-rpc/relay-dispatch.d.ts +4 -4
  93. package/dist/dashboard-rpc/relay-dispatch.d.ts.map +1 -1
  94. package/dist/dashboard-rpc/relay-dispatch.js +7 -7
  95. package/dist/dashboard-rpc/relay-dispatch.js.map +1 -1
  96. package/dist/dashboard-rpc/skills.d.ts +80 -0
  97. package/dist/dashboard-rpc/skills.d.ts.map +1 -0
  98. package/dist/dashboard-rpc/skills.js +84 -0
  99. package/dist/dashboard-rpc/skills.js.map +1 -0
  100. package/dist/dashboard-rpc/test-context.js +1 -1
  101. package/dist/dashboard-rpc/test-context.js.map +1 -1
  102. package/dist/events.d.ts +4 -3
  103. package/dist/events.d.ts.map +1 -1
  104. package/dist/loopback-host.d.ts +3 -5
  105. package/dist/loopback-host.d.ts.map +1 -1
  106. package/dist/loopback-host.js +3 -5
  107. package/dist/loopback-host.js.map +1 -1
  108. package/dist/machine-link.d.ts +21 -0
  109. package/dist/machine-link.d.ts.map +1 -0
  110. package/dist/machine-link.js +20 -0
  111. package/dist/machine-link.js.map +1 -0
  112. package/dist/module-server.d.ts +1 -1
  113. package/dist/module-types/dashboard/components/ui/switch.d.ts +7 -0
  114. package/dist/module-types/dashboard/lib/draft-handoff.d.ts +5 -9
  115. package/dist/module-types/dashboard/module/index.d.ts +46 -0
  116. package/dist/module-types/src/built-in.d.ts +45 -16
  117. package/dist/module-types/src/client.d.ts +2 -1
  118. package/dist/module-types/src/dashboard/bridge-endpoints.d.ts +5 -5
  119. package/dist/module-types/src/dashboard/http.d.ts +1 -1
  120. package/dist/module-types/src/dashboard/machine-call.d.ts +9 -0
  121. package/dist/module-types/src/dashboard/remote-run.d.ts +77 -32
  122. package/dist/module-types/src/dashboard/rpc-serve.d.ts +19 -25
  123. package/dist/module-types/src/dashboard/start-branch.d.ts +31 -0
  124. package/dist/module-types/src/dashboard/types.d.ts +6 -14
  125. package/dist/module-types/src/dashboard-rpc/context.d.ts +4 -4
  126. package/dist/module-types/src/dashboard-rpc/control.d.ts +1 -1
  127. package/dist/module-types/src/dashboard-rpc/events.d.ts +1 -1
  128. package/dist/module-types/src/dashboard-rpc/index.d.ts +2 -1
  129. package/dist/module-types/src/dashboard-rpc/machines.d.ts +51 -0
  130. package/dist/module-types/src/dashboard-rpc/modules.d.ts +1 -1
  131. package/dist/module-types/src/dashboard-rpc/projects.d.ts +2 -0
  132. package/dist/module-types/src/dashboard-rpc/reads.d.ts +3 -4
  133. package/dist/module-types/src/dashboard-rpc/relay-agent.d.ts +3 -3
  134. package/dist/module-types/src/dashboard-rpc/skills.d.ts +79 -0
  135. package/dist/module-types/src/events.d.ts +4 -3
  136. package/dist/module-types/src/loopback-host.d.ts +3 -5
  137. package/dist/module-types/src/machine-link.d.ts +20 -0
  138. package/dist/module-types/src/openagent-dir.d.ts +3 -5
  139. package/dist/module-types/src/project-commands.d.ts +4 -0
  140. package/dist/module-types/src/project-hooks.d.ts +8 -5
  141. package/dist/module-types/src/project-modules.d.ts +8 -6
  142. package/dist/module-types/src/registry.d.ts +59 -16
  143. package/dist/module-types/src/repository-address.d.ts +22 -0
  144. package/dist/module-types/src/screens.d.ts +13 -0
  145. package/dist/module-types/src/store/agent-store.d.ts +2 -2
  146. package/dist/module-types/src/store/branches.d.ts +1 -1
  147. package/dist/module-types/src/store/git-host.d.ts +1 -1
  148. package/dist/module-types/src/store/queue.d.ts +1 -1
  149. package/dist/module-types/src/store/runs.d.ts +1 -1
  150. package/dist/module-types/src/store/tickets.d.ts +1 -1
  151. package/dist/module-types/src/version.d.ts +1 -0
  152. package/dist/openagent-dir.d.ts +3 -5
  153. package/dist/openagent-dir.d.ts.map +1 -1
  154. package/dist/openagent-dir.js +3 -5
  155. package/dist/openagent-dir.js.map +1 -1
  156. package/dist/package-services.d.ts +27 -0
  157. package/dist/package-services.d.ts.map +1 -0
  158. package/dist/package-services.js +62 -0
  159. package/dist/package-services.js.map +1 -0
  160. package/dist/project-commands.d.ts +4 -0
  161. package/dist/project-commands.d.ts.map +1 -1
  162. package/dist/project-commands.js.map +1 -1
  163. package/dist/project-hooks.d.ts +8 -5
  164. package/dist/project-hooks.d.ts.map +1 -1
  165. package/dist/project-hooks.js +9 -6
  166. package/dist/project-hooks.js.map +1 -1
  167. package/dist/project-modules.d.ts +8 -6
  168. package/dist/project-modules.d.ts.map +1 -1
  169. package/dist/project-modules.js +7 -13
  170. package/dist/project-modules.js.map +1 -1
  171. package/dist/project.d.ts.map +1 -1
  172. package/dist/project.js +1 -2
  173. package/dist/project.js.map +1 -1
  174. package/dist/registry.d.ts +59 -16
  175. package/dist/registry.d.ts.map +1 -1
  176. package/dist/registry.js +91 -20
  177. package/dist/registry.js.map +1 -1
  178. package/dist/repository-address.d.ts +23 -0
  179. package/dist/repository-address.d.ts.map +1 -0
  180. package/dist/repository-address.js +38 -0
  181. package/dist/repository-address.js.map +1 -0
  182. package/dist/screens.d.ts +14 -0
  183. package/dist/screens.d.ts.map +1 -0
  184. package/dist/screens.js +40 -0
  185. package/dist/screens.js.map +1 -0
  186. package/dist/store/agent-store.d.ts +2 -2
  187. package/dist/store/agent-store.d.ts.map +1 -1
  188. package/dist/store/branches.d.ts +1 -1
  189. package/dist/store/branches.js +1 -1
  190. package/dist/store/git-host.d.ts +1 -1
  191. package/dist/store/git-host.js +2 -2
  192. package/dist/store/git-host.js.map +1 -1
  193. package/dist/store/queue.d.ts +1 -1
  194. package/dist/store/queue.js +1 -1
  195. package/dist/store/runs.d.ts +1 -1
  196. package/dist/store/runs.js +1 -1
  197. package/dist/store/test-branches.d.ts +0 -8
  198. package/dist/store/test-branches.d.ts.map +1 -1
  199. package/dist/store/test-branches.js +0 -24
  200. package/dist/store/test-branches.js.map +1 -1
  201. package/dist/store/tickets.d.ts +1 -1
  202. package/dist/store/tickets.js +1 -1
  203. package/dist/version.d.ts +2 -0
  204. package/dist/version.d.ts.map +1 -0
  205. package/dist/version.js +26 -0
  206. package/dist/version.js.map +1 -0
  207. package/package.json +19 -13
  208. package/dist/dashboard-bundle/assets/main-B98UOA3_.js +0 -140
  209. package/dist/dashboard-bundle/assets/main-ByRjbCiA.css +0 -2
  210. package/dist/dashboard-rpc/devices.d.ts +0 -9
  211. package/dist/dashboard-rpc/devices.d.ts.map +0 -1
  212. package/dist/dashboard-rpc/devices.js +0 -12
  213. package/dist/dashboard-rpc/devices.js.map +0 -1
  214. package/dist/install.d.ts +0 -31
  215. package/dist/install.d.ts.map +0 -1
  216. package/dist/install.js +0 -54
  217. package/dist/install.js.map +0 -1
  218. package/dist/module-types/src/dashboard-rpc/devices.d.ts +0 -8
  219. package/dist/module-types/src/openagent-gitignore.d.ts +0 -11
  220. package/dist/openagent-gitignore.d.ts +0 -12
  221. package/dist/openagent-gitignore.d.ts.map +0 -1
  222. package/dist/openagent-gitignore.js +0 -19
  223. package/dist/openagent-gitignore.js.map +0 -1
@@ -0,0 +1,175 @@
1
+ import { readFile } from 'node:fs/promises';
2
+ import { Readable } from 'node:stream';
3
+ import { eventsOf, isRunId } from '../store/index.js';
4
+ import { liveScreen } from '../screens.js';
5
+ import { end, readJsonBody } from './http.js';
6
+ import { machineFetch } from './machine-call.js';
7
+ /**
8
+ * A run's live screen, for whoever watches the run from this OpenAgent: on this computer, on a
9
+ * phone that got in, or on another computer that follows the run. A `screen` line in the run's
10
+ * diary names where the screen answers, on the loopback of the computer the run is on. That
11
+ * address is reached by nothing but the OpenAgent of that computer, which passes on two calls
12
+ * and no other:
13
+ *
14
+ * - `GET /_screen/stream?project=<id>&run=<id>`: what the screen shows, as the screen's own bytes.
15
+ * - `POST /_screen/input?project=<id>&run=<id>`: what the person did on it, as JSON.
16
+ *
17
+ * For a run this computer follows on another machine, both are asked of that machine
18
+ * (`/_relay/screen/…`), with this computer's key there.
19
+ *
20
+ * What a screen answers is written by whatever the agent ran, and for a run on another machine
21
+ * it comes from that machine. So it is never a page here: the bytes are answered as bytes no
22
+ * browser renders or runs, and the answer to an input is its status alone. What draws the screen
23
+ * is this OpenAgent's own.
24
+ */
25
+ export const SCREEN_PREFIX = '/_screen';
26
+ /** A person's click or a few typed letters, generously. */
27
+ const MAX_INPUT = 16 * 1024;
28
+ /** How long a screen gets to take an input. */
29
+ const INPUT_TIMEOUT_MS = 15_000;
30
+ /** The headers of every answer: bytes, kept by nobody, that no browser takes for a page or runs. */
31
+ const INERT = {
32
+ 'content-type': 'application/octet-stream',
33
+ 'cache-control': 'no-store',
34
+ 'x-content-type-options': 'nosniff',
35
+ 'content-security-policy': "sandbox; default-src 'none'",
36
+ };
37
+ /** The call a path names, when it names one. */
38
+ export function screenCallOf(pathname, prefix) {
39
+ const rest = pathname.slice(prefix.length + 1);
40
+ return pathname.startsWith(`${prefix}/`) && (rest === 'stream' || rest === 'input') ? rest : undefined;
41
+ }
42
+ /**
43
+ * The address one call to a screen goes to. Only a screen on this computer's own loopback is
44
+ * called, at its own two paths: the line that names it was written by whatever the agent ran.
45
+ */
46
+ export function screenCallAddress(screen, call) {
47
+ let at;
48
+ try {
49
+ at = new URL(screen);
50
+ }
51
+ catch {
52
+ return undefined;
53
+ }
54
+ if (at.protocol !== 'http:' || at.hostname !== '127.0.0.1' || !at.port || at.pathname !== '/')
55
+ return undefined;
56
+ return `http://127.0.0.1:${at.port}/${call}${at.search}`;
57
+ }
58
+ /**
59
+ * Where the live screen of the run whose diary is the file at `diary` answers; nothing when it
60
+ * has none, or no diary. Only the lines that can say so are read as JSON, a screen's and a run's
61
+ * end: a diary is as long as the run, and this is asked for as long as someone looks.
62
+ */
63
+ export async function screenInDiary(diary) {
64
+ const text = await readFile(diary, 'utf8').catch(() => '');
65
+ const lines = text.split('\n').flatMap(line => {
66
+ if (!line.includes('"screen"') && !line.includes('"ended"'))
67
+ return [];
68
+ try {
69
+ return [JSON.parse(line)];
70
+ }
71
+ catch {
72
+ return [];
73
+ }
74
+ });
75
+ return liveScreen(eventsOf(lines));
76
+ }
77
+ /** How long an answer of {@link kept} is good for: a person's clicks come in bursts, and each would read the whole diary. */
78
+ const KEPT_MS = 2_000;
79
+ /**
80
+ * `find`, asked at most once in a while for the same run, and once for all who ask at the same
81
+ * moment: where a screen answers changes only when a browser opens or closes. Only a run's own
82
+ * screen is kept: an ask that found none is asked again, and keeps nothing.
83
+ */
84
+ export function kept(find, now = Date.now) {
85
+ const answers = new Map();
86
+ return (projectId, agentId) => {
87
+ const key = `${projectId}\n${agentId}`;
88
+ const answer = answers.get(key);
89
+ if (answer && answer.until > now())
90
+ return answer.screen;
91
+ for (const [old, { until }] of answers)
92
+ if (until <= now())
93
+ answers.delete(old);
94
+ const screen = find(projectId, agentId);
95
+ answers.set(key, { screen, until: now() + KEPT_MS });
96
+ void screen.then(found => {
97
+ if (found === undefined && answers.get(key)?.screen === screen)
98
+ answers.delete(key);
99
+ }, () => {
100
+ if (answers.get(key)?.screen === screen)
101
+ answers.delete(key);
102
+ });
103
+ return screen;
104
+ };
105
+ }
106
+ /** Route a `/_screen/*` request of this computer's own dashboard, or of a device that got in. */
107
+ export async function handleScreenRequest(req, res, pathname, handlers) {
108
+ const call = screenCallOf(pathname, SCREEN_PREFIX);
109
+ if (!handlers || !call)
110
+ return end(res, 404, 'not found');
111
+ const query = new URL(req.url ?? '/', 'http://localhost').searchParams;
112
+ const projectId = query.get('project');
113
+ const agentId = query.get('run');
114
+ if (!projectId || !agentId)
115
+ return end(res, 400, 'missing project or run');
116
+ if (!isRunId(agentId))
117
+ return end(res, 400, 'not a run');
118
+ const remote = handlers.remote(agentId);
119
+ if (!remote)
120
+ return passToScreen(req, res, call, await handlers.local(projectId, agentId).catch(() => undefined));
121
+ const at = `${remote.url.replace(/\/+$/, '')}/_relay/screen/${call}?run=${encodeURIComponent(agentId)}&project=${encodeURIComponent(remote.project)}`;
122
+ await pass(req, res, call, init => machineFetch(at, remote.pin, { ...init, headers: { ...init.headers, authorization: `Bearer ${remote.key}` } }));
123
+ }
124
+ /** Pass one call on to the screen at `screen`, on this computer; a 404 when there is none. */
125
+ export async function passToScreen(req, res, call, screen) {
126
+ const at = screen === undefined ? undefined : screenCallAddress(screen, call);
127
+ if (at === undefined)
128
+ return end(res, 404, 'no screen');
129
+ await pass(req, res, call, init => fetch(at, { ...init, redirect: 'error' }));
130
+ }
131
+ /** Make the call with `ask`, and answer what it came to: a stream as inert bytes, an input as its status alone. */
132
+ async function pass(req, res, call, ask) {
133
+ const method = call === 'stream' ? 'GET' : 'POST';
134
+ if (req.method !== method)
135
+ return end(res, 405, 'method not allowed', { allow: method });
136
+ // Whoever asked going away ends the call: a screen nobody watches is asked for nothing.
137
+ const gone = new AbortController();
138
+ res.once('close', () => gone.abort());
139
+ if (call === 'input') {
140
+ let body;
141
+ try {
142
+ body = await readJsonBody(req, MAX_INPUT);
143
+ }
144
+ catch {
145
+ return end(res, 400, 'invalid request body');
146
+ }
147
+ const answer = await ask({
148
+ method,
149
+ headers: { 'content-type': 'application/json' },
150
+ body: JSON.stringify(body),
151
+ signal: AbortSignal.any([gone.signal, AbortSignal.timeout(INPUT_TIMEOUT_MS)]),
152
+ }).catch(() => undefined);
153
+ void answer?.body?.cancel().catch(() => { });
154
+ if (!answer)
155
+ return end(res, 502, 'the screen did not answer');
156
+ if (answer.status === 404)
157
+ return end(res, 404, 'no screen');
158
+ return end(res, answer.ok ? 204 : answer.status === 400 ? 400 : 502, '');
159
+ }
160
+ const answer = await ask({ method, headers: {}, signal: gone.signal }).catch(() => undefined);
161
+ if (res.destroyed)
162
+ return void answer?.body?.cancel().catch(() => { });
163
+ if (!answer?.ok || !answer.body) {
164
+ void answer?.body?.cancel().catch(() => { });
165
+ return end(res, answer?.status === 404 ? 404 : 502, answer?.status === 404 ? 'no screen' : 'the screen did not answer');
166
+ }
167
+ res.writeHead(200, INERT);
168
+ // The first picture may be a while away: the headers go now.
169
+ res.flushHeaders();
170
+ const bytes = Readable.fromWeb(answer.body);
171
+ // A screen that went away mid-stream ends the answer, so the watcher asks again instead of waiting for ever.
172
+ bytes.once('error', () => res.destroy());
173
+ bytes.pipe(res);
174
+ }
175
+ //# sourceMappingURL=screen.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"screen.js","sourceRoot":"","sources":["../../src/dashboard/screen.ts"],"names":[],"mappings":"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"}
@@ -9,8 +9,6 @@ import type { EventsSource, RemoteAgents } from './rpc-serve.js';
9
9
  export interface DashboardOptions {
10
10
  /** Port to bind. Default `4200`; pass `0` for an ephemeral port. */
11
11
  port?: number;
12
- /** Host to bind. Default `127.0.0.1` (localhost only). */
13
- host?: string;
14
12
  /**
15
13
  * Called when the browser starts a run (#345): the `sendStart` RPC reaches this through the
16
14
  * wired dashboard context. Wire it to the project's start hook.
@@ -44,40 +42,41 @@ export interface DashboardOptions {
44
42
  */
45
43
  clientBundleDir?: string;
46
44
  /**
47
- * The shared token that guards a non-loopback bind (#1051): with it set, every route (static
48
- * bundle, `/_rpc`, `/_relay`) needs a valid `oa_daemon` cookie or a matching
49
- * `?token=`, else 401. Omit for a loopback bind, where the guard is a no-op and local UX is
50
- * byte-identical. A separate concern from the CSRF origin check in rpc-serve.ts.
51
- */
52
- token?: string;
53
- /**
54
- * The live-events source for a run this daemon is relaying from a connected device (#1067):
45
+ * The live-events source for a run this daemon is relaying from a saved machine (#1067):
55
46
  * a stream for such a run, else undefined so `onEvents` tails the run's diary off disk.
56
47
  */
57
48
  eventsSource: EventsSource;
58
49
  /**
59
50
  * The relayed-agent lookup the read RPCs consult (#1067 slice 2). A run-scoped RPC uses it to
60
- * forward a remote agent's read/steer/handoff to the device that owns it.
51
+ * forward a remote agent's read/steer/handoff to the machine that owns it.
61
52
  */
62
53
  remote: RemoteAgents;
63
54
  /**
64
55
  * Serve a relay-started run's events back to the daemon that relayed it here (#1067): the
65
- * `/_relay/*` endpoints (start + events, plus the slice-2 `rpc`). All are fronted by the same
66
- * `token` guard above, so a device without the cookie cannot start or read a run.
56
+ * `/_relay/*` endpoints (start + events, plus the slice-2 `rpc`). The daemon listens on its
57
+ * own computer only, so a call from another machine reaches them through whatever this
58
+ * computer opened to the network, which lets in only a machine that holds a key of its own.
67
59
  */
68
60
  relay?: {
69
- tailEvents: (agentId: string, onEvent: (event: import('../events.js').OpenAgentEvent) => void) => () => void;
61
+ /** This machine's own id for its project cloned from an address, which is how a relayed call names one. */
62
+ project: (address: string) => Promise<string | undefined>;
63
+ tailEvents: (projectId: string, agentId: string, onEvent: (event: import('../events.js').OpenAgentEvent) => void) => () => void;
70
64
  /** Run one whitelisted run-scoped RPC against this daemon's own checkout (#1067 slice 2). */
71
- rpc?: (fn: string, args: unknown[]) => Promise<unknown>;
65
+ rpc?: (projectId: string, fn: string, args: unknown[]) => Promise<unknown>;
72
66
  };
67
+ /**
68
+ * Where the live screen of a run on this computer answers (screen.ts): what the `/_screen/*`
69
+ * routes, and the relay's for another machine, pass a watcher's calls on to. Absent leaves
70
+ * every screen route 404.
71
+ */
72
+ screen?: (projectId: string, agentId: string) => Promise<string | undefined>;
73
73
  /**
74
74
  * The browser bridge (#1237): the token a Claude web extension presents to report the question
75
75
  * its cloud session is parked on. Absent leaves every `/_bridge/*` route 404, which is default.
76
76
  *
77
- * Deliberately not {@link token}. That one guards a non-loopback bind and is absent on a normal
78
- * loopback daemon, where what keeps other origins out of `/_rpc` is the same-origin check.
79
- * The bridge is the one route meant to be reached from another origin, so neither protects it
80
- * and it authenticates on its own.
77
+ * What keeps other origins out of `/_rpc` is the same-origin check. The bridge is the one
78
+ * route meant to be reached from another origin, so that check does not protect it and it
79
+ * authenticates on its own.
81
80
  */
82
81
  bridgeToken?: string;
83
82
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/dashboard/server.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAA;AACtD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAC7C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAC/C,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAA;AAC/D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAA;AAK9D,OAAO,KAAK,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAC5G,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAA;AAOhE,0CAA0C;AAC1C,MAAM,WAAW,gBAAgB;IAC/B,oEAAoE;IACpE,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,0DAA0D;IAC1D,IAAI,CAAC,EAAE,MAAM,CAAA;IACb;;;OAGG;IACH,OAAO,EAAE,CACP,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,iBAAiB,EAC1B,SAAS,CAAC,EAAE,MAAM,KACf,gBAAgB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAA;IACjD;;;OAGG;IACH,YAAY,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,KAAK,OAAO,CAAC,gBAAgB,CAAC,GAAG,gBAAgB,CAAA;IAC5F,+HAA+H;IAC/H,eAAe,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,KAAK,OAAO,CAAC,mBAAmB,CAAC,GAAG,mBAAmB,CAAA;IAC1G;;;OAGG;IACH,WAAW,EAAE,gBAAgB,CAAA;IAC7B,yDAAyD;IACzD,KAAK,EAAE,WAAW,CAAA;IAClB,2EAA2E;IAC3E,MAAM,EAAE,YAAY,CAAA;IACpB,oFAAoF;IACpF,aAAa,EAAE,mBAAmB,CAAA;IAClC,iHAAiH;IACjH,aAAa,EAAE,kBAAkB,CAAA;IACjC;;;;;OAKG;IACH,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB;;;;;OAKG;IACH,KAAK,CAAC,EAAE,MAAM,CAAA;IACd;;;OAGG;IACH,YAAY,EAAE,YAAY,CAAA;IAC1B;;;OAGG;IACH,MAAM,EAAE,YAAY,CAAA;IACpB;;;;OAIG;IACH,KAAK,CAAC,EAAE;QACN,UAAU,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,KAAK,EAAE,OAAO,cAAc,EAAE,cAAc,KAAK,IAAI,KAAK,MAAM,IAAI,CAAA;QAC5G,6FAA6F;QAC7F,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;KACxD,CAAA;IACD;;;;;;;;OAQG;IACH,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,OAAO,CAAC,OAAO,uBAAuB,EAAE,aAAa,EAAE,CAAC,CAAA;CAChF;AAED,oEAAoE;AACpE,MAAM,WAAW,SAAS;IACxB,uBAAuB;IACvB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,mCAAmC;IACnC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;CACvB;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,gBAAgB,GAAG,OAAO,CAAC,SAAS,CAAC,CAwIzE"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/dashboard/server.ts"],"names":[],"mappings":"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"}
@@ -1,10 +1,10 @@
1
1
  import { createServer } from 'node:http';
2
- import { timingSafeEqual } from 'node:crypto';
3
2
  import { serveClientBundle } from './static.js';
4
3
  import { makeRpcMount, RPC_PREFIX, isSameOriginRequest, isExpectedHost } from './rpc-serve.js';
5
4
  import { requestPathname } from '../request-path.js';
6
5
  import { MODULES_PREFIX, serveModuleFile } from './module-serve.js';
7
6
  import { handleRelayRequest, RELAY_PREFIX } from './relay-endpoints.js';
7
+ import { handleScreenRequest, kept, SCREEN_PREFIX } from './screen.js';
8
8
  import { BRIDGE_PREFIX, EXPECTED_EXTENSION_VERSION, handleBridgeRequest } from './bridge-endpoints.js';
9
9
  import { bridgeQuestions } from './bridge-store.js';
10
10
  import { bridgeStarts } from './bridge-starts.js';
@@ -18,7 +18,6 @@ import { WEB_START_PREFIX, handleWebStartRequest } from './web-start-endpoints.j
18
18
  * {@link DashboardOptions.onStart} / {@link DashboardOptions.onAddProject}.
19
19
  */
20
20
  export function startDashboard(opts) {
21
- const host = opts.host ?? '127.0.0.1';
22
21
  const port = opts.port ?? 4200;
23
22
  const clientBundleDir = opts.clientBundleDir;
24
23
  // A broken install ships no built bundle (the published package always does), so serve
@@ -29,7 +28,7 @@ export function startDashboard(opts) {
29
28
  res.writeHead(503, { 'content-type': 'text/plain' });
30
29
  res.end('the dashboard bundle is not installed');
31
30
  });
32
- return listenDashboard(server, host, port, () => closeServer(server));
31
+ return listenDashboard(server, port, () => closeServer(server));
33
32
  }
34
33
  // The usage panel polls for the dashboard's whole life, not just during an agent:
35
34
  // it has to show where the account stands while nothing is running (#533).
@@ -45,17 +44,14 @@ export function startDashboard(opts) {
45
44
  bridgeBrowser: opts.bridgeBrowser,
46
45
  quota,
47
46
  models: opts.models,
48
- },
49
- // The bound host, so the mount can reject a rebound `Host`: a page on evil.com whose DNS
50
- // answers 127.0.0.1 is same-origin to the browser, so the Origin check alone lets it in.
51
- { host });
52
- // The device-to-daemon relay endpoints (#1067): wired only when an events tail is supplied.
53
- // Fronted by the same token guard as every other route below.
47
+ });
48
+ // The machine-to-daemon relay endpoints (#1067): wired only when an events tail is supplied.
49
+ const localScreen = opts.screen ? kept(opts.screen) : undefined;
54
50
  const relayHandlers = opts.relay
55
- ? { start: opts.onStart, tailEvents: opts.relay.tailEvents, ...(opts.relay.rpc ? { rpc: opts.relay.rpc } : {}) }
51
+ ? { project: opts.relay.project, start: opts.onStart, tailEvents: opts.relay.tailEvents, ...(opts.relay.rpc ? { rpc: opts.relay.rpc } : {}), ...(localScreen ? { screen: localScreen } : {}) }
56
52
  : undefined;
57
- // The browser bridge (#1237). Off unless a token was supplied, and it carries that token itself
58
- // rather than riding the shared-token guard (#1051), which a loopback daemon does not have.
53
+ const screenHandlers = localScreen ? { local: localScreen, remote: agentId => opts.remote.target(agentId) } : undefined;
54
+ // The browser bridge (#1237). Off unless a token was supplied, and it carries that token itself.
59
55
  const bridgeHandlers = opts.bridgeToken
60
56
  ? {
61
57
  token: opts.bridgeToken,
@@ -95,17 +91,13 @@ export function startDashboard(opts) {
95
91
  get: id => bridgeStarts().get(id),
96
92
  }
97
93
  : undefined;
98
- const token = opts.token;
99
94
  const server = createServer((req, res) => {
100
95
  const pathname = requestPathname(req);
101
96
  if (pathname === undefined) {
102
97
  res.writeHead(400, { 'content-type': 'text/plain' }).end('bad request');
103
98
  return;
104
99
  }
105
- // The browser bridge (#1237) is checked BEFORE the shared-token guard (#1051), and is the only route that is.
106
- // That guard's browser affordance is a `?token=` redirect meant for a human following a link,
107
- // which is meaningless to an extension posting JSON; the bridge presents its own bearer token
108
- // instead, so letting it past here costs nothing and skips a 302 it could not follow.
100
+ // The browser bridge (#1237) presents its own bearer token.
109
101
  if (pathname === BRIDGE_PREFIX || pathname.startsWith(`${BRIDGE_PREFIX}/`)) {
110
102
  void handleBridgeRequest(req, res, pathname, bridgeHandlers);
111
103
  return;
@@ -114,20 +106,30 @@ export function startDashboard(opts) {
114
106
  void handleWebStartRequest(req, res, pathname, webStartHandlers);
115
107
  return;
116
108
  }
117
- // #1051: one guard fronting every route on a non-loopback bind; a no-op when no token is set.
118
- if (token !== undefined && !authorizeDaemonRequest(req, res, token))
119
- return;
120
- // The device relay (#1067): another daemon posts a start here and streams the run's events back.
121
- // The token guard above is a no-op on a loopback bind, so — exactly like the RPC mount below —
122
- // the relay carries its own CSRF + DNS-rebinding guard, or a page the user merely visited could
123
- // POST /_relay/start to start a run (the real device caller sends no Origin and a loopback
124
- // Host, so both checks pass it; only a browser's cross-origin/rebound request is turned away).
109
+ // The machine relay (#1067): another daemon posts a start here and streams the run's events back.
110
+ // Exactly like the RPC mount below, the relay carries its own CSRF + DNS-rebinding guard, or a
111
+ // page the user merely visited could POST /_relay/start to start a run (a machine's call
112
+ // arrives with no Origin and a loopback Host, so both checks pass it; only a browser's
113
+ // cross-origin/rebound request is turned away).
125
114
  if (pathname === RELAY_PREFIX || pathname.startsWith(`${RELAY_PREFIX}/`)) {
126
- if (!guardBrowserOrigin(req, res, host))
115
+ if (!guardBrowserOrigin(req, res))
127
116
  return;
128
117
  void handleRelayRequest(req, res, pathname, relayHandlers);
129
118
  return;
130
119
  }
120
+ // A run's live screen (screen.ts): a click on it acts in the agent's browser, so it carries
121
+ // the same guard as the RPC mount.
122
+ if (pathname === SCREEN_PREFIX || pathname.startsWith(`${SCREEN_PREFIX}/`)) {
123
+ if (!guardBrowserOrigin(req, res) || !guardOwnPageFetch(req, res))
124
+ return;
125
+ void handleScreenRequest(req, res, pathname, screenHandlers).catch(() => {
126
+ if (!res.headersSent)
127
+ res.writeHead(500, { 'content-type': 'text/plain' }).end('the screen failed');
128
+ else
129
+ res.destroy();
130
+ });
131
+ return;
132
+ }
131
133
  if (pathname === RPC_PREFIX || pathname.startsWith(`${RPC_PREFIX}/`)) {
132
134
  void rpcMount(req, res);
133
135
  return;
@@ -143,21 +145,26 @@ export function startDashboard(opts) {
143
145
  }
144
146
  void serveClientBundle(req, res, clientBundleDir);
145
147
  });
146
- return listenDashboard(server, host, port, async () => {
148
+ return listenDashboard(server, port, async () => {
147
149
  // Stop polling with the server: the poller outlives every agent by design,
148
150
  // so nothing else would ever end it.
149
151
  quota.stop();
150
152
  await closeServer(server);
151
153
  });
152
154
  }
155
+ /**
156
+ * The one address the dashboard listens on: this computer's own. Whatever opens OpenAgent to a
157
+ * network is a package of its own, which listens there and passes what it lets in on to here.
158
+ */
159
+ const DASHBOARD_HOST = '127.0.0.1';
153
160
  /** Bind the server and resolve a {@link Dashboard} handle; rejects if the port is already taken. */
154
- function listenDashboard(server, host, port, close) {
161
+ function listenDashboard(server, port, close) {
155
162
  return new Promise((resolvePromise, rejectPromise) => {
156
163
  server.once('error', rejectPromise);
157
- server.listen(port, host, () => {
164
+ server.listen(port, DASHBOARD_HOST, () => {
158
165
  server.removeListener('error', rejectPromise);
159
166
  const address = server.address();
160
- resolvePromise({ url: `http://${host}:${address.port}`, close });
167
+ resolvePromise({ url: `http://${DASHBOARD_HOST}:${address.port}`, close });
161
168
  });
162
169
  });
163
170
  }
@@ -167,65 +174,29 @@ function closeServer(server) {
167
174
  return new Promise(resolvePromise => server.close(() => resolvePromise()));
168
175
  }
169
176
  /**
170
- * The CSRF + DNS-rebinding guard the RPC mount applies, lifted to the device relay, which
171
- * dispatches outside it. The relay is state-changing (it starts a run on this machine) and is
172
- * wired unconditionally on a loopback bind, where the shared-token guard is a no-op, so without
173
- * this a page the user merely visited reaches it. Returns true to admit the request; on rejection
174
- * it has already answered 403.
177
+ * A watched screen makes the run's computer draw pictures, and watching is a plain GET, which a
178
+ * browser sends with no `Origin`. So a screen's routes also read what a browser says of where a
179
+ * request comes from: one another site's page made, and one that is the address bar's own (a
180
+ * download with no end), is turned away. A browser that says nothing (a page reached over plain
181
+ * HTTP on the Wi-Fi) is let by, as before. Returns true to admit; on rejection it has answered 403.
175
182
  */
176
- function guardBrowserOrigin(req, res, host) {
177
- if (isSameOriginRequest(req) && isExpectedHost(req, host))
183
+ function guardOwnPageFetch(req, res) {
184
+ const site = req.headers['sec-fetch-site'];
185
+ if ((site === undefined || site === 'same-origin') && req.headers['sec-fetch-mode'] !== 'navigate')
178
186
  return true;
179
187
  res.writeHead(403, { 'content-type': 'text/plain' }).end('forbidden');
180
188
  return false;
181
189
  }
182
- /** The cookie a bootstrapped browser carries on every same-origin request (#1051). */
183
- const DAEMON_COOKIE = 'oa_daemon';
184
190
  /**
185
- * The non-loopback bind guard (#1051): a request needs a valid `oa_daemon` cookie or a matching
186
- * `?token=`, else 401. A valid `?token=` sets the cookie and 302s to the clean path so the token
187
- * leaves the URL bar, history, and Referer after one hop; the cookie then rides RPC, the events
188
- * Channel, and the MJPEG `<img>` screencast alike (all same-origin), which a bearer header cannot
189
- * reach. Returns true to admit the request, false once it has answered (401 or the redirect).
191
+ * The CSRF + DNS-rebinding guard the RPC mount applies, lifted to the machine relay, which
192
+ * dispatches outside it. The relay is state-changing (it starts a run on this machine), so
193
+ * without this a page the user merely visited reaches it. Returns true to admit the request; on rejection
194
+ * it has already answered 403.
190
195
  */
191
- function authorizeDaemonRequest(req, res, token) {
192
- // Safe to re-parse: requestPathname already parsed this same url without throwing (#938).
193
- const url = new URL(req.url ?? '/', 'http://localhost');
194
- const queryToken = url.searchParams.get('token');
195
- if (queryToken !== null && tokensMatch(queryToken, token)) {
196
- url.searchParams.delete('token');
197
- const query = url.searchParams.toString();
198
- res.writeHead(302, {
199
- // Lax, not Strict: the device-hop (#1052) is a cross-origin top-level nav, and a Strict cookie set on it is withheld from the redirect right after, so the clean path 401s. Lax still rides top-level GET navs; CSRF stays covered by the same-origin check on /_rpc.
200
- 'set-cookie': `${DAEMON_COOKIE}=${token}; HttpOnly; SameSite=Lax; Path=/`,
201
- location: url.pathname + (query ? `?${query}` : ''),
202
- });
203
- res.end();
204
- return false;
205
- }
206
- const cookieToken = readCookie(req.headers.cookie, DAEMON_COOKIE);
207
- if (cookieToken !== undefined && tokensMatch(cookieToken, token))
196
+ function guardBrowserOrigin(req, res) {
197
+ if (isSameOriginRequest(req) && isExpectedHost(req))
208
198
  return true;
209
- res.writeHead(401, { 'content-type': 'text/plain' });
210
- res.end('unauthorized');
199
+ res.writeHead(403, { 'content-type': 'text/plain' }).end('forbidden');
211
200
  return false;
212
201
  }
213
- /** Constant-time token compare (#1051). The length check first, since `timingSafeEqual` throws on
214
- * unequal-length buffers and a length mismatch cannot be a match anyway. */
215
- function tokensMatch(a, b) {
216
- const ab = Buffer.from(a);
217
- const bb = Buffer.from(b);
218
- return ab.length === bb.length && timingSafeEqual(ab, bb);
219
- }
220
- /** One cookie's value out of a `Cookie` header, or `undefined`. */
221
- function readCookie(header, name) {
222
- if (!header)
223
- return undefined;
224
- for (const part of header.split(';')) {
225
- const eq = part.indexOf('=');
226
- if (eq !== -1 && part.slice(0, eq).trim() === name)
227
- return part.slice(eq + 1).trim();
228
- }
229
- return undefined;
230
- }
231
202
  //# sourceMappingURL=server.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/dashboard/server.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/dashboard/server.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * The branch agents start from in the project at `cwd`: origin's default branch as this clone has
3
+ * it, else the branch the folder is on (a project with no remote starts an agent from its last
4
+ * local commit). `ref` is what git is asked, `name` what a person reads. None where the folder is
5
+ * on no branch, or is no repository.
6
+ */
7
+ export declare function startBranch(cwd: string): Promise<{
8
+ ref: string;
9
+ name: string;
10
+ } | undefined>;
11
+ /** A skill that is in the folder and not on the branch agents start from. */
12
+ export interface Waiting {
13
+ /** The branch it has yet to reach, by name. */
14
+ branch: string;
15
+ /** Whether the branch the folder is on has it: an agent started from that branch does. */
16
+ here: boolean;
17
+ }
18
+ /**
19
+ * Which of the skills `names`, all in the project's folder, are waiting to reach the branch agents
20
+ * start from. A skill is said to be waiting only when that is known: an agent's checkout fetches
21
+ * the remote before it starts, so before a skill is called waiting against a remote branch, this
22
+ * clone's copy of that branch is fetched too (at most once a minute per project), or a pull
23
+ * request merged a moment ago would keep its skill waiting here.
24
+ */
25
+ export declare function waitingSkills(cwd: string, names: readonly string[]): Promise<{
26
+ start?: {
27
+ ref: string;
28
+ name: string;
29
+ };
30
+ waiting: Map<string, Waiting>;
31
+ }>;
32
+ //# sourceMappingURL=start-branch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"start-branch.d.ts","sourceRoot":"","sources":["../../src/dashboard/start-branch.ts"],"names":[],"mappings":"AAIA;;;;;GAKG;AACH,wBAAsB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,CAAC,CAKjG;AAED,6EAA6E;AAC7E,MAAM,WAAW,OAAO;IACtB,+CAA+C;IAC/C,MAAM,EAAE,MAAM,CAAA;IACd,0FAA0F;IAC1F,IAAI,EAAE,OAAO,CAAA;CACd;AAQD;;;;;;GAMG;AACH,wBAAsB,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAAC;IAAE,KAAK,CAAC,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IAAC,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,CAAC,CAe5J"}
@@ -0,0 +1,47 @@
1
+ import { nodeGitRunner, originDefaultBranch } from '@openagt/agent-data';
2
+ import { skillsOn } from '@openagt/init';
3
+ import { currentBranch } from './git-status.js';
4
+ /**
5
+ * The branch agents start from in the project at `cwd`: origin's default branch as this clone has
6
+ * it, else the branch the folder is on (a project with no remote starts an agent from its last
7
+ * local commit). `ref` is what git is asked, `name` what a person reads. None where the folder is
8
+ * on no branch, or is no repository.
9
+ */
10
+ export async function startBranch(cwd) {
11
+ const main = await originDefaultBranch(cwd).catch(() => undefined);
12
+ if (main !== undefined)
13
+ return { ref: main, name: main.slice('origin/'.length) };
14
+ const local = await currentBranch(cwd).catch(() => undefined);
15
+ return local !== undefined && local !== 'HEAD' ? { ref: 'HEAD', name: local } : undefined;
16
+ }
17
+ /** How long this clone's copy of the remote's default branch counts as fresh, per project. */
18
+ const FRESH_MS = 60_000;
19
+ /** How long a read waits for the fetch that freshens it; the fetch itself goes on. */
20
+ const FETCH_WAIT_MS = 5_000;
21
+ const fetched = new Map();
22
+ /**
23
+ * Which of the skills `names`, all in the project's folder, are waiting to reach the branch agents
24
+ * start from. A skill is said to be waiting only when that is known: an agent's checkout fetches
25
+ * the remote before it starts, so before a skill is called waiting against a remote branch, this
26
+ * clone's copy of that branch is fetched too (at most once a minute per project), or a pull
27
+ * request merged a moment ago would keep its skill waiting here.
28
+ */
29
+ export async function waitingSkills(cwd, names) {
30
+ const start = await startBranch(cwd);
31
+ if (!start || names.length === 0)
32
+ return { ...(start ? { start } : {}), waiting: new Map() };
33
+ let on = await skillsOn(cwd, start.ref);
34
+ let missing = names.filter(name => !on.has(name));
35
+ if (missing.length > 0 && start.ref !== 'HEAD' && Date.now() - (fetched.get(cwd) ?? 0) > FRESH_MS) {
36
+ fetched.set(cwd, Date.now());
37
+ const fetch = nodeGitRunner()(['fetch', '--quiet', 'origin', start.name], cwd).catch(() => undefined);
38
+ await Promise.race([fetch, new Promise(resolve => setTimeout(resolve, FETCH_WAIT_MS))]);
39
+ on = await skillsOn(cwd, start.ref);
40
+ missing = names.filter(name => !on.has(name));
41
+ }
42
+ if (missing.length === 0)
43
+ return { start, waiting: new Map() };
44
+ const here = start.ref === 'HEAD' ? { has: () => false } : await skillsOn(cwd, 'HEAD');
45
+ return { start, waiting: new Map(missing.map(name => [name, { branch: start.name, here: here.has(name) }])) };
46
+ }
47
+ //# sourceMappingURL=start-branch.js.map