@midhunxavier/code-flow 0.0.0-stage → 0.1.0-preview.3

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 (319) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +141 -2
  3. package/bin/codeflow.mjs +8 -0
  4. package/bin/launcher.mjs +127 -0
  5. package/dist/remote-host.json +1 -0
  6. package/licenses/inter.txt +92 -0
  7. package/licenses/preact.txt +21 -0
  8. package/licenses/signals-core.txt +21 -0
  9. package/licenses/signals.txt +21 -0
  10. package/licenses/typescript-notices.txt +193 -0
  11. package/licenses/typescript.txt +55 -0
  12. package/licenses/uqr.txt +22 -0
  13. package/licenses/xterm-fit.txt +19 -0
  14. package/licenses/xterm.txt +21 -0
  15. package/package.json +34 -4
  16. package/public/assets/changes-62ZIEQSN.js +1 -0
  17. package/public/assets/chunk-2PZVOKID.js +1 -0
  18. package/public/assets/chunk-4D5IENEB.js +1 -0
  19. package/public/assets/chunk-5SARP5MU.js +1 -0
  20. package/public/assets/chunk-63YLZ3PR.js +1 -0
  21. package/public/assets/chunk-7FUHKF2M.js +1 -0
  22. package/public/assets/chunk-APQEVJ2K.js +1 -0
  23. package/public/assets/chunk-CGOZQMEZ.js +2 -0
  24. package/public/assets/chunk-J4VYS3KV.js +2 -0
  25. package/public/assets/chunk-L7TUCIYF.js +1 -0
  26. package/public/assets/chunk-SIHDWM2Y.js +154 -0
  27. package/public/assets/chunk-TEJVYIKC.js +1 -0
  28. package/public/assets/code-browser-VB2HGZSG.js +4 -0
  29. package/public/assets/filtered-tasks-ES5CP4KV.js +1 -0
  30. package/public/assets/interactive-browser-7F5ZXRUV.js +7 -0
  31. package/public/assets/join-project-6RTFHNCA.js +1 -0
  32. package/public/assets/main-65EW73SB.js +1 -0
  33. package/public/assets/project-invitations-view-GMPWGWYM.js +1 -0
  34. package/public/assets/settings-UB5Q4AQM.js +9 -0
  35. package/public/assets/styles-18792BB4.css +32 -0
  36. package/public/assets/team-server-wizard-2GLDWS6D.js +8 -0
  37. package/public/assets/terminal-IWAIM4DE.js +62 -0
  38. package/public/assets.json +1 -0
  39. package/public/bundle-meta.json +1 -0
  40. package/public/docs/.nojekyll +0 -0
  41. package/public/docs/accessibility.html +19 -0
  42. package/public/docs/acp-agents.html +117 -0
  43. package/public/docs/agent-containers.html +79 -0
  44. package/public/docs/api.html +1130 -0
  45. package/public/docs/app.js +342 -0
  46. package/public/docs/application-improvements.html +275 -0
  47. package/public/docs/architecture-explorer.html +19 -0
  48. package/public/docs/architecture.html +149 -0
  49. package/public/docs/auto-team.html +148 -0
  50. package/public/docs/automations.html +109 -0
  51. package/public/docs/checkpoint-review.html +37 -0
  52. package/public/docs/code-hosts.html +35 -0
  53. package/public/docs/code-intelligence.html +35 -0
  54. package/public/docs/configuration.html +346 -0
  55. package/public/docs/context-inspection.html +23 -0
  56. package/public/docs/coordinated-changes.html +28 -0
  57. package/public/docs/deferred-runs.html +25 -0
  58. package/public/docs/dependency-discovery.html +19 -0
  59. package/public/docs/documentation.html +84 -0
  60. package/public/docs/dynamic-teams-evaluation.html +174 -0
  61. package/public/docs/dynamic-teams-implementation-plan.html +882 -0
  62. package/public/docs/dynamic-teams-implementation-review-1.html +141 -0
  63. package/public/docs/dynamic-teams-plan-review-0.html +204 -0
  64. package/public/docs/extensions.html +42 -0
  65. package/public/docs/external-sources.html +96 -0
  66. package/public/docs/filesystem-policy.html +26 -0
  67. package/public/docs/filtered-tasks.html +44 -0
  68. package/public/docs/font-license.txt +92 -0
  69. package/public/docs/getting-started.html +143 -0
  70. package/public/docs/github-review-threads.html +26 -0
  71. package/public/docs/github.html +157 -0
  72. package/public/docs/help.html +69 -0
  73. package/public/docs/index.html +88 -0
  74. package/public/docs/installation.html +80 -0
  75. package/public/docs/launch-profiles.html +48 -0
  76. package/public/docs/maintenance.html +60 -0
  77. package/public/docs/memory-claims.html +31 -0
  78. package/public/docs/memory-storage.html +58 -0
  79. package/public/docs/notifications.html +39 -0
  80. package/public/docs/patterns.html +195 -0
  81. package/public/docs/performance-results.html +210 -0
  82. package/public/docs/performance.html +166 -0
  83. package/public/docs/project-conventions.html +22 -0
  84. package/public/docs/project-first-navigation-plan.html +587 -0
  85. package/public/docs/project-teams-implementation-plan.html +772 -0
  86. package/public/docs/project-teams.html +129 -0
  87. package/public/docs/provider-compatibility.html +20 -0
  88. package/public/docs/releasing.html +65 -0
  89. package/public/docs/remote-workers.html +64 -0
  90. package/public/docs/review-inbox.html +26 -0
  91. package/public/docs/run-storage.html +23 -0
  92. package/public/docs/runs.html +141 -0
  93. package/public/docs/search.json +1 -0
  94. package/public/docs/security.html +133 -0
  95. package/public/docs/shared-projects.html +31 -0
  96. package/public/docs/ssh-projects.html +60 -0
  97. package/public/docs/style.css +768 -0
  98. package/public/docs/task-reruns.html +30 -0
  99. package/public/docs/team-collaboration.html +412 -0
  100. package/public/docs/verification.html +22 -0
  101. package/public/docs/vscode.html +53 -0
  102. package/public/docs/worker-permission-verification.html +131 -0
  103. package/public/index.html +17 -0
  104. package/scripts/check-node.mjs +7 -0
  105. package/scripts/codeflow.mjs +55 -0
  106. package/scripts/computer-use.swift +64 -0
  107. package/scripts/pty.py +273 -0
  108. package/src/acp-connections.js +110 -0
  109. package/src/adapters/acp-presets.js +37 -0
  110. package/src/adapters/acp-types.js +0 -0
  111. package/src/adapters/acp.js +328 -0
  112. package/src/adapters/agent-tools.js +28 -0
  113. package/src/adapters/agy-auth.js +67 -0
  114. package/src/adapters/agy-isolation.js +242 -0
  115. package/src/adapters/agy-tools.js +45 -0
  116. package/src/adapters/agy.js +326 -0
  117. package/src/adapters/claude-stream.js +58 -0
  118. package/src/adapters/claude.js +282 -0
  119. package/src/adapters/codex-app-server.js +555 -0
  120. package/src/adapters/codex.js +311 -0
  121. package/src/adapters/errors.js +57 -0
  122. package/src/adapters/index.js +91 -0
  123. package/src/adapters/managed-permissions.js +37 -0
  124. package/src/adapters/model-discovery.js +100 -0
  125. package/src/adapters/process.js +433 -0
  126. package/src/adapters/team-tools.js +103 -0
  127. package/src/adapters/types.js +0 -0
  128. package/src/agent-browser.js +688 -0
  129. package/src/agent-computer.js +88 -0
  130. package/src/agent-container.js +155 -0
  131. package/src/agent-team-definitions.js +131 -0
  132. package/src/agent-tool-client.mjs +79 -0
  133. package/src/agent-tools.js +296 -0
  134. package/src/approvals.js +134 -0
  135. package/src/architecture.js +456 -0
  136. package/src/assets.js +44 -0
  137. package/src/automation.js +901 -0
  138. package/src/browser-files.js +293 -0
  139. package/src/browser-ownership.js +150 -0
  140. package/src/certificate-renewal.js +75 -0
  141. package/src/chat-family.js +25 -0
  142. package/src/chat-handoff.js +87 -0
  143. package/src/checkpoint-review.js +72 -0
  144. package/src/checks.js +303 -0
  145. package/src/code-host-git.js +102 -0
  146. package/src/code-hosts-api.js +99 -0
  147. package/src/code-hosts.js +482 -0
  148. package/src/code-intelligence-worker.mjs +452 -0
  149. package/src/code-intelligence.js +141 -0
  150. package/src/collab/api.js +365 -0
  151. package/src/collab/checkpoints.js +198 -0
  152. package/src/collab/connections.js +139 -0
  153. package/src/collab/host-execution.js +347 -0
  154. package/src/collab/hub-client.js +210 -0
  155. package/src/collab/link-api.js +229 -0
  156. package/src/collab/link.js +595 -0
  157. package/src/collab/model.js +496 -0
  158. package/src/collab/runner.js +1014 -0
  159. package/src/collab/store.js +1452 -0
  160. package/src/collab/terminals.js +361 -0
  161. package/src/collaboration-reviews.js +116 -0
  162. package/src/config.js +48 -0
  163. package/src/context-budget.js +14 -0
  164. package/src/context-inspection.js +204 -0
  165. package/src/context.js +154 -0
  166. package/src/conventions.js +283 -0
  167. package/src/coordinated-api.js +247 -0
  168. package/src/deferred-launch.js +82 -0
  169. package/src/deferred-runs.js +515 -0
  170. package/src/dependency-health.js +35 -0
  171. package/src/diff.js +43 -0
  172. package/src/docs-help.js +316 -0
  173. package/src/doctor.js +232 -0
  174. package/src/documentation-changes.js +20 -0
  175. package/src/engine.js +5258 -0
  176. package/src/env.js +44 -0
  177. package/src/execution-budget.js +8 -0
  178. package/src/experience.js +50 -0
  179. package/src/extensions.js +144 -0
  180. package/src/filesystem-access.js +107 -0
  181. package/src/filesystem-policy.js +238 -0
  182. package/src/filtered-task-limits.js +93 -0
  183. package/src/filtered-tasks-api.js +53 -0
  184. package/src/filtered-tasks.js +576 -0
  185. package/src/frame-policy.js +66 -0
  186. package/src/fs.js +57 -0
  187. package/src/git.js +626 -0
  188. package/src/github-review-threads.js +181 -0
  189. package/src/github.js +538 -0
  190. package/src/http.js +69 -0
  191. package/src/improve-settings.js +38 -0
  192. package/src/improve.js +187 -0
  193. package/src/integrations.js +373 -0
  194. package/src/integrity.js +259 -0
  195. package/src/journey-api.js +77 -0
  196. package/src/journey-replay.js +65 -0
  197. package/src/journey-store.js +97 -0
  198. package/src/journeys.js +60 -0
  199. package/src/json.js +81 -0
  200. package/src/launch-profiles.js +292 -0
  201. package/src/learnings.js +80 -0
  202. package/src/local-app-url.js +19 -0
  203. package/src/log.js +39 -0
  204. package/src/maintenance.js +335 -0
  205. package/src/memory-analysis.js +182 -0
  206. package/src/memory-claims.js +153 -0
  207. package/src/memory-sqlite.js +236 -0
  208. package/src/memory.js +552 -0
  209. package/src/merge-validation.js +58 -0
  210. package/src/model-catalog.js +239 -0
  211. package/src/model-research.js +91 -0
  212. package/src/notes.js +176 -0
  213. package/src/notifications.js +413 -0
  214. package/src/patterns/auto-team-model.js +230 -0
  215. package/src/patterns/auto-team.js +816 -0
  216. package/src/patterns/council.js +199 -0
  217. package/src/patterns/debate.js +188 -0
  218. package/src/patterns/findings.js +141 -0
  219. package/src/patterns/index.js +21 -0
  220. package/src/patterns/loop.js +158 -0
  221. package/src/patterns/pipeline.js +125 -0
  222. package/src/patterns/prompts.js +181 -0
  223. package/src/patterns/race.js +147 -0
  224. package/src/patterns/schemas.js +40 -0
  225. package/src/patterns/solo.js +46 -0
  226. package/src/patterns/supervisor.js +235 -0
  227. package/src/patterns/task-draft.js +29 -0
  228. package/src/patterns/task-review.js +45 -0
  229. package/src/patterns/tdd.js +231 -0
  230. package/src/patterns/team-strategies.js +67 -0
  231. package/src/performance.js +43 -0
  232. package/src/persistence-status.js +35 -0
  233. package/src/phone-sessions.js +96 -0
  234. package/src/preview-overlay.js +392 -0
  235. package/src/preview.js +230 -0
  236. package/src/privacy.js +23 -0
  237. package/src/project-report.js +22 -0
  238. package/src/project-team-budget.js +22 -0
  239. package/src/project-team-model.js +225 -0
  240. package/src/project-team-policy.js +42 -0
  241. package/src/project-team-store.js +234 -0
  242. package/src/project-team-usage.js +24 -0
  243. package/src/project-teams-api.js +43 -0
  244. package/src/project-teams.js +644 -0
  245. package/src/projects.js +290 -0
  246. package/src/provider-eligibility.js +9 -0
  247. package/src/readiness.js +98 -0
  248. package/src/remote-tls.js +66 -0
  249. package/src/remote-workers/bundles.js +198 -0
  250. package/src/remote-workers/client.js +332 -0
  251. package/src/remote-workers/durability.js +37 -0
  252. package/src/remote-workers/protocol.js +68 -0
  253. package/src/remote-workers/stdio.js +138 -0
  254. package/src/remote-workers/worker.js +304 -0
  255. package/src/remote.js +204 -0
  256. package/src/repo-config.js +201 -0
  257. package/src/repo-coordination.js +725 -0
  258. package/src/repo-tree.js +106 -0
  259. package/src/repository-identity.js +13 -0
  260. package/src/retention-policy.js +466 -0
  261. package/src/review-inbox.js +38 -0
  262. package/src/routing.js +49 -0
  263. package/src/run-analysis.js +111 -0
  264. package/src/run-cold-store.js +231 -0
  265. package/src/run-environment.js +15 -0
  266. package/src/run-history.js +91 -0
  267. package/src/run-log.js +160 -0
  268. package/src/run-permissions.js +111 -0
  269. package/src/run-projection.js +77 -0
  270. package/src/run-recovery.js +53 -0
  271. package/src/run-status.js +56 -0
  272. package/src/serve.js +138 -0
  273. package/src/server.js +2871 -0
  274. package/src/shared-access.js +103 -0
  275. package/src/shared-accounts.js +381 -0
  276. package/src/shared-api.js +239 -0
  277. package/src/shell.js +346 -0
  278. package/src/ship.js +344 -0
  279. package/src/slots.js +74 -0
  280. package/src/snapshot.js +388 -0
  281. package/src/source-context.js +17 -0
  282. package/src/sse-writer.js +70 -0
  283. package/src/ssh-projects/bootstrap.mjs +95 -0
  284. package/src/ssh-projects/config.js +45 -0
  285. package/src/ssh-projects/gateway.js +143 -0
  286. package/src/ssh-projects/manager.js +320 -0
  287. package/src/ssh-projects/team-autostart.mjs +93 -0
  288. package/src/ssh-projects/team-remove.mjs +69 -0
  289. package/src/ssh-projects/team-status.mjs +39 -0
  290. package/src/ssh-projects/transport.js +133 -0
  291. package/src/stats.js +139 -0
  292. package/src/store.js +544 -0
  293. package/src/stream.js +91 -0
  294. package/src/sweeps.js +241 -0
  295. package/src/tailscale.js +101 -0
  296. package/src/task-draft.js +23 -0
  297. package/src/task-team.js +164 -0
  298. package/src/team-evaluation.js +243 -0
  299. package/src/team-mailbox.js +160 -0
  300. package/src/team-memory.js +84 -0
  301. package/src/team-rerun-graph.js +15 -0
  302. package/src/team-reruns.js +130 -0
  303. package/src/team-scheduler.js +121 -0
  304. package/src/team-steering.js +21 -0
  305. package/src/team-template-store.js +98 -0
  306. package/src/team-templates.js +117 -0
  307. package/src/team-tool-client.mjs +79 -0
  308. package/src/team-tools.js +235 -0
  309. package/src/teams.js +0 -0
  310. package/src/templates.js +62 -0
  311. package/src/transcript.js +134 -0
  312. package/src/verification-integrity.js +27 -0
  313. package/src/verification.js +183 -0
  314. package/src/watch.js +195 -0
  315. package/src/work-queue.js +47 -0
  316. package/src/workflow-control.js +83 -0
  317. package/src/workspace-api.js +207 -0
  318. package/src/workspace-changes.js +61 -0
  319. package/src/workspace.js +146 -0
@@ -0,0 +1,39 @@
1
+ // Read-only probe. Never installs, starts or reconnects a team server, and never
2
+ // emits its owner token or the secret path in a device-access link.
3
+ import { readFile } from "node:fs/promises";
4
+ import { homedir } from "node:os";
5
+ import { join } from "node:path";
6
+
7
+ async function status() {
8
+ let runtime;
9
+ try { runtime = JSON.parse(await readFile(join(homedir(), ".codeflow/team-server/runtime.json"), "utf8")); }
10
+ catch (error) { return { state: error.code === "ENOENT" ? "not-installed" : "unavailable" }; }
11
+ if (runtime?.protocol !== 1 || !Number.isInteger(runtime.port) || runtime.port < 1 || runtime.port > 65535
12
+ || !/^[a-f0-9]{64}$/.test(runtime.token ?? "") || !/^[a-f0-9]{32}$/.test(runtime.instance ?? "")) return { state: "unavailable" };
13
+ const get = async path => {
14
+ const response = await fetch(`http://127.0.0.1:${runtime.port}${path}`, {
15
+ headers: { authorization: `Bearer ${runtime.token}` }, signal: AbortSignal.timeout(4000), redirect: "error",
16
+ });
17
+ if (!response.ok) throw new Error("Status unavailable");
18
+ return response.json();
19
+ };
20
+ try {
21
+ const identity = await get("/api/team-host-runtime");
22
+ if (identity.instance !== runtime.instance) return { state: "unavailable" };
23
+ const remote = await get("/api/remote");
24
+ let address;
25
+ if (remote.enabled && remote.lan && remote.secure && !remote.lanError) {
26
+ try {
27
+ const url = new URL(remote.tailscaleUrl ?? remote.lanUrls?.[0]);
28
+ if (url.protocol === "https:" && !url.username && !url.password) address = url.origin;
29
+ } catch { /* An absent or invalid address cannot be shared. */ }
30
+ }
31
+ return {
32
+ state: "running",
33
+ access: !remote.enabled || !remote.lan ? "disabled" : remote.lanError ? "error" : address ? "ready" : "incomplete",
34
+ ...(address ? { address } : {}),
35
+ network: remote.transport === "tailscale" ? "Tailscale" : "Private network",
36
+ };
37
+ } catch { return { state: "unavailable" }; }
38
+ }
39
+ console.log("CODEFLOW_TEAM_STATUS " + JSON.stringify(await status()));
@@ -0,0 +1,133 @@
1
+ import { spawn } from "node:child_process";
2
+ import { mkdtemp, rm } from "node:fs/promises";
3
+ import { tmpdir } from "node:os";
4
+ import { isAbsolute, join } from "node:path";
5
+ import { Duplex } from "node:stream";
6
+ const validSshHost = (host) => typeof host === "string" && /^[A-Za-z0-9][A-Za-z0-9._@-]{0,199}$/.test(host);
7
+ function validSshOptions(options) {
8
+ return (options.port === void 0 || Number.isInteger(options.port) && Number(options.port) >= 1 && Number(options.port) <= 65535) && (options.identityFile === void 0 || typeof options.identityFile === "string" && options.identityFile.length <= 4096 && (isAbsolute(options.identityFile) || options.identityFile.startsWith("~/")) && !/[\x00-\x1f\x7f%]/.test(options.identityFile));
9
+ }
10
+ const quote = (value) => `'${value.replaceAll("'", "'\\''")}'`;
11
+ const OPTIONS = ["-T", "-a", "-k", "-o", "GSSAPIDelegateCredentials=no", "-o", "SendEnv=-*", "-o", "BatchMode=yes", "-o", "StrictHostKeyChecking=yes", "-o", "ForwardAgent=no", "-o", "ForwardX11=no", "-o", "PermitLocalCommand=no", "-o", "RemoteCommand=none", "-o", "ClearAllForwardings=yes", "-o", "ConnectTimeout=15", "-o", "ServerAliveInterval=15", "-o", "ServerAliveCountMax=3"];
12
+ class SshTransport {
13
+ constructor(host, binary = "ssh", options = {}) {
14
+ this.host = host;
15
+ this.binary = binary;
16
+ this.options = options;
17
+ if (!validSshHost(host)) throw new Error("Enter an SSH host alias or user@hostname");
18
+ if (!validSshOptions(options)) throw new Error("Use a port from 1 to 65535 and an absolute or ~/ SSH key path without control characters or % tokens");
19
+ }
20
+ directory = "";
21
+ children = /* @__PURE__ */ new Set();
22
+ closed = false;
23
+ async init() {
24
+ this.directory = await mkdtemp(join(tmpdir(), "cf-ssh-"));
25
+ }
26
+ start(args, command) {
27
+ if (this.closed) throw new Error("SSH connection is closed");
28
+ const env = {};
29
+ for (const name of ["PATH", "HOME", "USER", "LOGNAME", "SSH_AUTH_SOCK", "SYSTEMROOT", "SystemRoot", "TMPDIR"]) if (process.env[name]) env[name] = process.env[name];
30
+ const connection = [...this.options.port ? ["-p", String(this.options.port)] : [], ...this.options.identityFile ? ["-i", this.options.identityFile] : []];
31
+ const child = spawn(this.binary, [...OPTIONS, ...connection, "-o", "ControlMaster=auto", "-o", "ControlPersist=60", "-o", `ControlPath=${join(this.directory, "socket")}`, ...args, this.host, ...command ? [command] : []], { env, stdio: ["pipe", "pipe", "pipe"] });
32
+ this.children.add(child);
33
+ child.once("close", () => this.children.delete(child));
34
+ return child;
35
+ }
36
+ async bootstrap(code, payload, teamServer = false) {
37
+ const command = `exec sh -c ${quote(`exec "\${SHELL:-/bin/sh}" -lc ${quote(`exec node --input-type=module -e ${quote(code)}${teamServer ? " -- --team-server" : ""}`)}`)}`;
38
+ const child = this.start([], command);
39
+ return new Promise((resolve, reject) => {
40
+ let stdout = "", stderr = "", settled = false;
41
+ const finish = (error) => {
42
+ if (settled) return;
43
+ settled = true;
44
+ clearTimeout(timer);
45
+ error ? reject(error) : resolve(stdout);
46
+ };
47
+ const timer = setTimeout(() => {
48
+ child.kill();
49
+ finish(new Error("SSH setup timed out. Check the server's SSH login, Node.js and ~/.codeflow/ssh-host/host.log."));
50
+ }, 12e4);
51
+ child.stdout.on("data", (data) => {
52
+ stdout += data;
53
+ if (stdout.length > 64 * 1024) {
54
+ child.kill();
55
+ finish(new Error("SSH setup produced too much output"));
56
+ }
57
+ });
58
+ child.stderr.on("data", (data) => {
59
+ stderr = (stderr + data).slice(-8192);
60
+ });
61
+ child.once("error", finish);
62
+ child.stdin.on("error", () => void 0);
63
+ child.once("close", (code2) => finish(code2 === 0 ? void 0 : new Error(`SSH setup failed: ${stderr.trim() || `exit ${code2}`}. Verify ${this.host} with the same port and key in an SSH terminal first.`)));
64
+ child.stdin.end(payload);
65
+ });
66
+ }
67
+ open(port, hostname = "127.0.0.1") {
68
+ if (!Number.isInteger(port) || port < 1 || port > 65535) throw new Error("Invalid remote port");
69
+ if (!["localhost", "127.0.0.1", "::1", "[::1]"].includes(hostname)) throw new Error("SSH forwards only remote loopback addresses");
70
+ const host = hostname.includes(":") ? "[::1]" : hostname;
71
+ const child = this.start(["-W", `${host}:${port}`]);
72
+ const stream = new Duplex({
73
+ read() {
74
+ child.stdout.resume();
75
+ },
76
+ write(chunk, encoding, callback) {
77
+ child.stdin.write(chunk, encoding, callback);
78
+ },
79
+ final(callback) {
80
+ child.stdin.end(callback);
81
+ },
82
+ destroy(error, callback) {
83
+ child.stdin.destroy();
84
+ child.stdout.destroy();
85
+ child.kill();
86
+ callback(error);
87
+ }
88
+ });
89
+ child.stdout.on("data", (chunk) => {
90
+ if (!stream.push(chunk)) child.stdout.pause();
91
+ });
92
+ child.stdout.on("end", () => stream.push(null));
93
+ child.stdout.on("error", (error) => stream.destroy(error));
94
+ stream.on("error", () => void 0);
95
+ child.stdin.on("error", () => void 0);
96
+ let stderr = "";
97
+ child.stderr.on("data", (data) => {
98
+ stderr = (stderr + data).slice(-2048);
99
+ });
100
+ child.once("error", (error) => stream.destroy(error));
101
+ child.once("close", (code) => {
102
+ if (code) stream.destroy(new Error(`SSH connection failed: ${stderr.trim() || `exit ${code}`}`));
103
+ });
104
+ return stream;
105
+ }
106
+ async close() {
107
+ if (this.closed) return;
108
+ const child = this.start(["-O", "exit"]);
109
+ child.on("error", () => void 0);
110
+ child.stdout.resume();
111
+ child.stderr.resume();
112
+ child.stdin.end();
113
+ await new Promise((resolve) => {
114
+ const timer = setTimeout(() => {
115
+ child.kill();
116
+ resolve();
117
+ }, 2e3);
118
+ child.once("close", () => {
119
+ clearTimeout(timer);
120
+ resolve();
121
+ });
122
+ });
123
+ this.closed = true;
124
+ for (const process2 of this.children) process2.kill();
125
+ await rm(this.directory, { recursive: true, force: true });
126
+ }
127
+ }
128
+ export {
129
+ SshTransport,
130
+ quote,
131
+ validSshHost,
132
+ validSshOptions
133
+ };
package/src/stats.js ADDED
@@ -0,0 +1,139 @@
1
+ import { runPassed, checksLabel } from "./run-status.js";
2
+ const tokensOf = (r) => (r.usage.inputTokens ?? 0) + (r.usage.outputTokens ?? 0);
3
+ const lastLine = (stat) => stat?.trim().split("\n").pop()?.trim();
4
+ function computeStats(all, filter = {}) {
5
+ const runs = all.filter((r) => (!filter.repo || r.repo === filter.repo) && (!filter.since || r.createdAt >= filter.since));
6
+ const agents = /* @__PURE__ */ new Map();
7
+ const patterns = /* @__PURE__ */ new Map();
8
+ const cohorts = /* @__PURE__ */ new Map();
9
+ const agent = (id) => {
10
+ let a = agents.get(id);
11
+ if (!a) {
12
+ a = { agent: id, runs: 0, steps: 0, writeSteps: 0, failures: 0, inputTokens: 0, outputTokens: 0, cacheReadTokens: 0, costUsd: 0, ms: 0, judged: 0, passed: 0, attributedJudged: 0, attributedPassed: 0, sharedJudged: 0, confidence: { low: 0, high: 1, samples: 0 }, raceEntries: 0, raceWins: 0, loopSolves: 0, findings: 0, agreedFindings: 0 };
13
+ agents.set(id, a);
14
+ }
15
+ return a;
16
+ };
17
+ for (const r of runs) {
18
+ const sourceKind = r.source?.kind ?? "task";
19
+ const key = JSON.stringify([r.repo, r.pattern, sourceKind]);
20
+ const cohort = cohorts.get(key) ?? { key, repo: r.repo, pattern: r.pattern, sourceKind, runs: 0, judged: 0, passed: 0, tokens: 0, costUsd: 0, ms: 0 };
21
+ cohorts.set(key, cohort);
22
+ cohort.runs++;
23
+ if (r.status === "done" && ["Passed", "Failed"].includes(checksLabel(r))) {
24
+ cohort.judged++;
25
+ if (runPassed(r)) cohort.passed++;
26
+ }
27
+ cohort.tokens += tokensOf(r);
28
+ cohort.costUsd += r.usage.costUsd ?? 0;
29
+ cohort.ms += r.endedAt ? r.endedAt - r.createdAt : 0;
30
+ const p = patterns.get(r.pattern) ?? { pattern: r.pattern, runs: 0, done: 0, passed: 0, failing: 0, failed: 0, stopped: 0, flagged: 0, proven: 0, weak: 0, unproven: 0, ended: 0, ms: 0, steps: 0, tokens: 0, costUsd: 0 };
31
+ patterns.set(r.pattern, p);
32
+ p.runs++;
33
+ if (r.status === "done") p.done++;
34
+ if (r.status === "failed") p.failed++;
35
+ if (r.status === "stopped") p.stopped++;
36
+ if (runPassed(r)) p.passed++;
37
+ if (checksLabel(r) === "Failed") p.failing++;
38
+ if (r.integrity && Object.keys(r.integrity).length) p.flagged++;
39
+ if (r.facts?.proof === "proven") p.proven++;
40
+ if (r.facts?.proof === "weak") p.weak++;
41
+ if (r.facts?.proof === "unproven") p.unproven++;
42
+ if (r.endedAt) {
43
+ p.ended++;
44
+ p.ms += r.endedAt - r.createdAt;
45
+ }
46
+ p.steps += r.usage.agentSteps;
47
+ p.tokens += tokensOf(r);
48
+ p.costUsd += r.usage.costUsd ?? 0;
49
+ const writers = Object.values(r.usage.byAgent ?? {}).filter((u) => u && u.writeSteps > 0).length;
50
+ for (const [id, u] of Object.entries(r.usage.byAgent ?? {})) {
51
+ if (!u) continue;
52
+ const a = agent(id);
53
+ a.runs++;
54
+ a.steps += u.steps;
55
+ a.writeSteps += u.writeSteps;
56
+ a.failures += u.failures;
57
+ a.inputTokens += u.inputTokens;
58
+ a.outputTokens += u.outputTokens;
59
+ a.cacheReadTokens += u.cacheReadTokens;
60
+ a.costUsd += u.costUsd;
61
+ a.ms += u.ms;
62
+ if (u.writeSteps && r.status === "done" && ["Passed", "Failed"].includes(checksLabel(r))) {
63
+ a.judged++;
64
+ if (runPassed(r)) a.passed++;
65
+ if (writers === 1) {
66
+ a.attributedJudged++;
67
+ if (runPassed(r)) a.attributedPassed++;
68
+ } else a.sharedJudged++;
69
+ }
70
+ }
71
+ for (const id of r.facts?.entrants ?? []) agent(id).raceEntries++;
72
+ if (r.facts?.winner) agent(r.facts.winner).raceWins++;
73
+ if (r.facts?.solvedBy) agent(r.facts.solvedBy).loopSolves++;
74
+ for (const f of r.review?.findings ?? []) {
75
+ for (const id of f.raisedBy) {
76
+ agent(id).findings++;
77
+ if (f.raisedBy.length > 1) agent(id).agreedFindings++;
78
+ }
79
+ }
80
+ }
81
+ for (const a of agents.values()) a.confidence = { ...confidenceInterval(a.attributedPassed, a.attributedJudged), samples: a.attributedJudged };
82
+ const groups = /* @__PURE__ */ new Map();
83
+ for (const r of runs) {
84
+ if (!r.group) continue;
85
+ const g = groups.get(r.group.id) ?? { id: r.group.id, task: r.task, createdAt: r.createdAt, runs: [] };
86
+ groups.set(r.group.id, g);
87
+ g.createdAt = Math.min(g.createdAt, r.createdAt);
88
+ g.runs.push({
89
+ id: r.id,
90
+ label: r.group.label,
91
+ pattern: r.pattern,
92
+ roles: r.roles,
93
+ status: r.status,
94
+ verdict: runPassed(r) ? "passed" : checksLabel(r) === "Failed" ? "failing" : void 0,
95
+ ms: r.endedAt ? r.endedAt - r.createdAt : void 0,
96
+ steps: r.usage.agentSteps,
97
+ tokens: tokensOf(r),
98
+ costUsd: r.usage.costUsd ?? 0,
99
+ flagged: Object.values(r.integrity ?? {}).flat().length,
100
+ proof: r.facts?.proof,
101
+ stat: lastLine(r.artifacts.find((a) => a.stat?.trim())?.stat)
102
+ });
103
+ }
104
+ return {
105
+ runs: runs.length,
106
+ tokens: runs.reduce((n, r) => n + tokensOf(r), 0),
107
+ costUsd: runs.reduce((n, r) => n + (r.usage.costUsd ?? 0), 0),
108
+ ms: runs.reduce((n, r) => n + (r.endedAt ? r.endedAt - r.createdAt : 0), 0),
109
+ agents: [...agents.values()].sort((a, b) => b.runs - a.runs),
110
+ patterns: [...patterns.values()].sort((a, b) => b.runs - a.runs),
111
+ groups: [...groups.values()].sort((a, b) => b.createdAt - a.createdAt),
112
+ cohorts: [...cohorts.values()].sort((a, b) => b.runs - a.runs)
113
+ };
114
+ }
115
+ const MIN_SAMPLES = 3;
116
+ function rankAgents(runs, repo, cohort = {}) {
117
+ const comparable = runs.filter((r) => (!cohort.pattern || r.pattern === cohort.pattern) && (!cohort.sourceKind || (r.source?.kind ?? "task") === cohort.sourceKind));
118
+ const stats = computeStats(comparable, { repo }).agents.filter((a) => a.attributedJudged >= MIN_SAMPLES);
119
+ if (stats.length < 2) return { order: [], why: {} };
120
+ const ranked = stats.sort((a, b) => b.confidence.low - a.confidence.low || b.attributedJudged - a.attributedJudged || a.agent.localeCompare(b.agent));
121
+ return {
122
+ order: ranked.map((a) => a.agent),
123
+ why: Object.fromEntries(ranked.map((a) => [a.agent, `${a.attributedPassed} of ${a.attributedJudged} runs passed in this repo with this provider as the sole writer; 95% interval ${Math.round(100 * a.confidence.low)}\u2013${Math.round(100 * a.confidence.high)}%${a.sharedJudged ? `; ${a.sharedJudged} shared outcomes excluded` : ""}${cohort.pattern ? `; ${cohort.pattern} tasks` : "; task difficulty varies"}`]))
124
+ };
125
+ }
126
+ function confidenceInterval(passed, samples) {
127
+ if (!samples) return { low: 0, high: 1 };
128
+ const z = 1.959963984540054;
129
+ const p = Math.max(0, Math.min(samples, passed)) / samples;
130
+ const denominator = 1 + z * z / samples;
131
+ const center = (p + z * z / (2 * samples)) / denominator;
132
+ const margin = z * Math.sqrt(p * (1 - p) / samples + z * z / (4 * samples * samples)) / denominator;
133
+ return { low: Math.max(0, center - margin), high: Math.min(1, center + margin) };
134
+ }
135
+ export {
136
+ computeStats,
137
+ confidenceInterval,
138
+ rankAgents
139
+ };