@chipschat/protocol 0.0.0-stage → 1.0.1

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 (371) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +56 -2
  3. package/dist/generated/types.d.ts +4052 -0
  4. package/dist/generated/types.d.ts.map +1 -0
  5. package/dist/generated/types.js +7 -0
  6. package/dist/generated/types.js.map +1 -0
  7. package/dist/src/address.d.ts +106 -0
  8. package/dist/src/address.d.ts.map +1 -0
  9. package/dist/src/address.js +141 -0
  10. package/dist/src/address.js.map +1 -0
  11. package/dist/src/agent-context-windows.d.ts +235 -0
  12. package/dist/src/agent-context-windows.d.ts.map +1 -0
  13. package/dist/src/agent-context-windows.js +213 -0
  14. package/dist/src/agent-context-windows.js.map +1 -0
  15. package/dist/src/agent-heartbeats.d.ts +106 -0
  16. package/dist/src/agent-heartbeats.d.ts.map +1 -0
  17. package/dist/src/agent-heartbeats.js +111 -0
  18. package/dist/src/agent-heartbeats.js.map +1 -0
  19. package/dist/src/agent-models.d.ts +158 -0
  20. package/dist/src/agent-models.d.ts.map +1 -0
  21. package/dist/src/agent-models.js +171 -0
  22. package/dist/src/agent-models.js.map +1 -0
  23. package/dist/src/agent-place.d.ts +76 -0
  24. package/dist/src/agent-place.d.ts.map +1 -0
  25. package/dist/src/agent-place.js +80 -0
  26. package/dist/src/agent-place.js.map +1 -0
  27. package/dist/src/agents.d.ts +24 -0
  28. package/dist/src/agents.d.ts.map +1 -0
  29. package/dist/src/agents.js +58 -0
  30. package/dist/src/agents.js.map +1 -0
  31. package/dist/src/capabilities.d.ts +121 -0
  32. package/dist/src/capabilities.d.ts.map +1 -0
  33. package/dist/src/capabilities.js +120 -0
  34. package/dist/src/capabilities.js.map +1 -0
  35. package/dist/src/checklist.d.ts +19 -0
  36. package/dist/src/checklist.d.ts.map +1 -0
  37. package/dist/src/checklist.js +22 -0
  38. package/dist/src/checklist.js.map +1 -0
  39. package/dist/src/commands.d.ts +50 -0
  40. package/dist/src/commands.d.ts.map +1 -0
  41. package/dist/src/commands.js +274 -0
  42. package/dist/src/commands.js.map +1 -0
  43. package/dist/src/connectors.d.ts +90 -0
  44. package/dist/src/connectors.d.ts.map +1 -0
  45. package/dist/src/connectors.js +119 -0
  46. package/dist/src/connectors.js.map +1 -0
  47. package/dist/src/context-files.d.ts +304 -0
  48. package/dist/src/context-files.d.ts.map +1 -0
  49. package/dist/src/context-files.js +247 -0
  50. package/dist/src/context-files.js.map +1 -0
  51. package/dist/src/context.d.ts +369 -0
  52. package/dist/src/context.d.ts.map +1 -0
  53. package/dist/src/context.js +526 -0
  54. package/dist/src/context.js.map +1 -0
  55. package/dist/src/direct-asks.d.ts +36 -0
  56. package/dist/src/direct-asks.d.ts.map +1 -0
  57. package/dist/src/direct-asks.js +43 -0
  58. package/dist/src/direct-asks.js.map +1 -0
  59. package/dist/src/envelope.d.ts +70 -0
  60. package/dist/src/envelope.d.ts.map +1 -0
  61. package/dist/src/envelope.js +46 -0
  62. package/dist/src/envelope.js.map +1 -0
  63. package/dist/src/events/catalogue.d.ts +50 -0
  64. package/dist/src/events/catalogue.d.ts.map +1 -0
  65. package/dist/src/events/catalogue.js +70 -0
  66. package/dist/src/events/catalogue.js.map +1 -0
  67. package/dist/src/events/chips-to-harness.d.ts +37 -0
  68. package/dist/src/events/chips-to-harness.d.ts.map +1 -0
  69. package/dist/src/events/chips-to-harness.js +511 -0
  70. package/dist/src/events/chips-to-harness.js.map +1 -0
  71. package/dist/src/events/harness-to-chips.d.ts +38 -0
  72. package/dist/src/events/harness-to-chips.d.ts.map +1 -0
  73. package/dist/src/events/harness-to-chips.js +593 -0
  74. package/dist/src/events/harness-to-chips.js.map +1 -0
  75. package/dist/src/events/index.d.ts +6 -0
  76. package/dist/src/events/index.d.ts.map +1 -0
  77. package/dist/src/events/index.js +5 -0
  78. package/dist/src/events/index.js.map +1 -0
  79. package/dist/src/events/workspace.d.ts +222 -0
  80. package/dist/src/events/workspace.d.ts.map +1 -0
  81. package/dist/src/events/workspace.js +1039 -0
  82. package/dist/src/events/workspace.js.map +1 -0
  83. package/dist/src/exchange.d.ts +262 -0
  84. package/dist/src/exchange.d.ts.map +1 -0
  85. package/dist/src/exchange.js +413 -0
  86. package/dist/src/exchange.js.map +1 -0
  87. package/dist/src/first-names.d.ts +29 -0
  88. package/dist/src/first-names.d.ts.map +1 -0
  89. package/dist/src/first-names.js +80 -0
  90. package/dist/src/first-names.js.map +1 -0
  91. package/dist/src/frames.d.ts +526 -0
  92. package/dist/src/frames.d.ts.map +1 -0
  93. package/dist/src/frames.js +346 -0
  94. package/dist/src/frames.js.map +1 -0
  95. package/dist/src/harness-jobs.d.ts +313 -0
  96. package/dist/src/harness-jobs.d.ts.map +1 -0
  97. package/dist/src/harness-jobs.js +210 -0
  98. package/dist/src/harness-jobs.js.map +1 -0
  99. package/dist/src/ids/index.d.ts +3 -0
  100. package/dist/src/ids/index.d.ts.map +1 -0
  101. package/dist/src/ids/index.js +2 -0
  102. package/dist/src/ids/index.js.map +1 -0
  103. package/dist/src/ids/ulid.d.ts +96 -0
  104. package/dist/src/ids/ulid.d.ts.map +1 -0
  105. package/dist/src/ids/ulid.js +212 -0
  106. package/dist/src/ids/ulid.js.map +1 -0
  107. package/dist/src/index.d.ts +81 -0
  108. package/dist/src/index.d.ts.map +1 -0
  109. package/dist/src/index.js +47 -0
  110. package/dist/src/index.js.map +1 -0
  111. package/dist/src/invite-link.d.ts +64 -0
  112. package/dist/src/invite-link.d.ts.map +1 -0
  113. package/dist/src/invite-link.js +99 -0
  114. package/dist/src/invite-link.js.map +1 -0
  115. package/dist/src/join.d.ts +188 -0
  116. package/dist/src/join.d.ts.map +1 -0
  117. package/dist/src/join.js +190 -0
  118. package/dist/src/join.js.map +1 -0
  119. package/dist/src/limits.d.ts +50 -0
  120. package/dist/src/limits.d.ts.map +1 -0
  121. package/dist/src/limits.js +106 -0
  122. package/dist/src/limits.js.map +1 -0
  123. package/dist/src/matters.d.ts +22 -0
  124. package/dist/src/matters.d.ts.map +1 -0
  125. package/dist/src/matters.js +26 -0
  126. package/dist/src/matters.js.map +1 -0
  127. package/dist/src/mentions.d.ts +63 -0
  128. package/dist/src/mentions.d.ts.map +1 -0
  129. package/dist/src/mentions.js +129 -0
  130. package/dist/src/mentions.js.map +1 -0
  131. package/dist/src/names.d.ts +58 -0
  132. package/dist/src/names.d.ts.map +1 -0
  133. package/dist/src/names.js +192 -0
  134. package/dist/src/names.js.map +1 -0
  135. package/dist/src/no-reply.d.ts +17 -0
  136. package/dist/src/no-reply.d.ts.map +1 -0
  137. package/dist/src/no-reply.js +48 -0
  138. package/dist/src/no-reply.js.map +1 -0
  139. package/dist/src/notifications.d.ts +81 -0
  140. package/dist/src/notifications.d.ts.map +1 -0
  141. package/dist/src/notifications.js +65 -0
  142. package/dist/src/notifications.js.map +1 -0
  143. package/dist/src/pages.d.ts +32 -0
  144. package/dist/src/pages.d.ts.map +1 -0
  145. package/dist/src/pages.js +32 -0
  146. package/dist/src/pages.js.map +1 -0
  147. package/dist/src/pairing.d.ts +99 -0
  148. package/dist/src/pairing.d.ts.map +1 -0
  149. package/dist/src/pairing.js +163 -0
  150. package/dist/src/pairing.js.map +1 -0
  151. package/dist/src/primitives.d.ts +267 -0
  152. package/dist/src/primitives.d.ts.map +1 -0
  153. package/dist/src/primitives.js +279 -0
  154. package/dist/src/primitives.js.map +1 -0
  155. package/dist/src/project.d.ts +335 -0
  156. package/dist/src/project.d.ts.map +1 -0
  157. package/dist/src/project.js +499 -0
  158. package/dist/src/project.js.map +1 -0
  159. package/dist/src/ranges.d.ts +31 -0
  160. package/dist/src/ranges.d.ts.map +1 -0
  161. package/dist/src/ranges.js +51 -0
  162. package/dist/src/ranges.js.map +1 -0
  163. package/dist/src/relay.d.ts +177 -0
  164. package/dist/src/relay.d.ts.map +1 -0
  165. package/dist/src/relay.js +147 -0
  166. package/dist/src/relay.js.map +1 -0
  167. package/dist/src/room-files.d.ts +146 -0
  168. package/dist/src/room-files.d.ts.map +1 -0
  169. package/dist/src/room-files.js +135 -0
  170. package/dist/src/room-files.js.map +1 -0
  171. package/dist/src/room-note.d.ts +213 -0
  172. package/dist/src/room-note.d.ts.map +1 -0
  173. package/dist/src/room-note.js +457 -0
  174. package/dist/src/room-note.js.map +1 -0
  175. package/dist/src/space-icons.d.ts +68 -0
  176. package/dist/src/space-icons.d.ts.map +1 -0
  177. package/dist/src/space-icons.js +142 -0
  178. package/dist/src/space-icons.js.map +1 -0
  179. package/dist/src/spend.d.ts +57 -0
  180. package/dist/src/spend.d.ts.map +1 -0
  181. package/dist/src/spend.js +94 -0
  182. package/dist/src/spend.js.map +1 -0
  183. package/dist/src/visibility.d.ts +170 -0
  184. package/dist/src/visibility.d.ts.map +1 -0
  185. package/dist/src/visibility.js +218 -0
  186. package/dist/src/visibility.js.map +1 -0
  187. package/fixtures/agent.asked.json +15 -0
  188. package/fixtures/agent.attached.json +15 -0
  189. package/fixtures/agent.deleted.json +16 -0
  190. package/fixtures/agent.fork.json +14 -0
  191. package/fixtures/agent.lock_set.json +13 -0
  192. package/fixtures/agent.registered.json +17 -0
  193. package/fixtures/agent.released.json +16 -0
  194. package/fixtures/agent.updated.json +14 -0
  195. package/fixtures/approval.executed.json +16 -0
  196. package/fixtures/approval.request.json +45 -0
  197. package/fixtures/approval.resolved.json +20 -0
  198. package/fixtures/approval.routed.json +20 -0
  199. package/fixtures/artifact.create.json +18 -0
  200. package/fixtures/attachment.fetched.json +15 -0
  201. package/fixtures/attachment.limits_set.json +15 -0
  202. package/fixtures/budget.warning.json +20 -0
  203. package/fixtures/checkpoint.json +16 -0
  204. package/fixtures/context.compacted.json +16 -0
  205. package/fixtures/context.usage.json +17 -0
  206. package/fixtures/exchange.limits_set.json +15 -0
  207. package/fixtures/exchange.set.json +13 -0
  208. package/fixtures/feedback.json +21 -0
  209. package/fixtures/frames/ack.json +6 -0
  210. package/fixtures/frames/context.edit.json +11 -0
  211. package/fixtures/frames/context_window.change.json +9 -0
  212. package/fixtures/frames/context_window.compact.json +8 -0
  213. package/fixtures/frames/error.json +6 -0
  214. package/fixtures/frames/event.json +20 -0
  215. package/fixtures/frames/events.json +39 -0
  216. package/fixtures/frames/folder.open.json +6 -0
  217. package/fixtures/frames/folder.open.page.json +7 -0
  218. package/fixtures/frames/folder.run.json +8 -0
  219. package/fixtures/frames/folder.run_state.json +12 -0
  220. package/fixtures/frames/heartbeat.change.json +10 -0
  221. package/fixtures/frames/hello.json +18 -0
  222. package/fixtures/frames/job.change.json +9 -0
  223. package/fixtures/frames/join.json +19 -0
  224. package/fixtures/frames/model.change.json +10 -0
  225. package/fixtures/frames/ping.json +4 -0
  226. package/fixtures/frames/pong.json +4 -0
  227. package/fixtures/frames/presence.json +12 -0
  228. package/fixtures/frames/receipt.json +5 -0
  229. package/fixtures/frames/restart.json +5 -0
  230. package/fixtures/frames/subscribe.json +6 -0
  231. package/fixtures/handoff.json +20 -0
  232. package/fixtures/harness.removed.json +15 -0
  233. package/fixtures/harness.transferred.json +15 -0
  234. package/fixtures/hello.json +61 -0
  235. package/fixtures/join.allowed.json +20 -0
  236. package/fixtures/join.denied.json +17 -0
  237. package/fixtures/lane.updated.json +17 -0
  238. package/fixtures/membership.added.json +16 -0
  239. package/fixtures/membership.removed.json +14 -0
  240. package/fixtures/membership.replaced.json +15 -0
  241. package/fixtures/message.deleted.json +15 -0
  242. package/fixtures/message.edited.json +15 -0
  243. package/fixtures/message.handed.json +14 -0
  244. package/fixtures/message.heard.json +14 -0
  245. package/fixtures/message.held.json +14 -0
  246. package/fixtures/message.hidden.json +14 -0
  247. package/fixtures/message.new.json +96 -0
  248. package/fixtures/message.overheard.json +22 -0
  249. package/fixtures/message.pinned.json +14 -0
  250. package/fixtures/message.post.json +14 -0
  251. package/fixtures/message.shown.json +14 -0
  252. package/fixtures/message.unpinned.json +14 -0
  253. package/fixtures/person.face_set.json +17 -0
  254. package/fixtures/person.joined.json +16 -0
  255. package/fixtures/person.removed.json +16 -0
  256. package/fixtures/person.renamed.json +14 -0
  257. package/fixtures/policy.updated.json +30 -0
  258. package/fixtures/project.changed.json +21 -0
  259. package/fixtures/question.answered.json +23 -0
  260. package/fixtures/question.ask.json +37 -0
  261. package/fixtures/receipt.json +15 -0
  262. package/fixtures/relay.set.json +12 -0
  263. package/fixtures/role.changed.json +15 -0
  264. package/fixtures/run.cancel.json +15 -0
  265. package/fixtures/run.completed.json +20 -0
  266. package/fixtures/run.failed.json +20 -0
  267. package/fixtures/run.pause.json +15 -0
  268. package/fixtures/run.plan.json +24 -0
  269. package/fixtures/run.requested.json +34 -0
  270. package/fixtures/run.resume.json +15 -0
  271. package/fixtures/run.started.json +33 -0
  272. package/fixtures/run.status.json +17 -0
  273. package/fixtures/run.steer.json +21 -0
  274. package/fixtures/session.ended.json +15 -0
  275. package/fixtures/session.renamed.json +15 -0
  276. package/fixtures/session.started.json +17 -0
  277. package/fixtures/space.claimed.json +15 -0
  278. package/fixtures/space.created.json +14 -0
  279. package/fixtures/space.erased.json +13 -0
  280. package/fixtures/space.lead_set.json +13 -0
  281. package/fixtures/space.lock_set.json +13 -0
  282. package/fixtures/space.spend_ceiling_set.json +13 -0
  283. package/fixtures/space.updated.json +14 -0
  284. package/fixtures/step.log.json +26 -0
  285. package/fixtures/task.json +22 -0
  286. package/fixtures/turn.passed.json +14 -0
  287. package/fixtures/usage.json +21 -0
  288. package/fixtures/workspace.renamed.json +13 -0
  289. package/generated/agent-connect.json +13966 -0
  290. package/generated/schema/agent.asked.json +114 -0
  291. package/generated/schema/agent.attached.json +465 -0
  292. package/generated/schema/agent.deleted.json +127 -0
  293. package/generated/schema/agent.fork.json +107 -0
  294. package/generated/schema/agent.lock_set.json +105 -0
  295. package/generated/schema/agent.registered.json +130 -0
  296. package/generated/schema/agent.released.json +129 -0
  297. package/generated/schema/agent.updated.json +151 -0
  298. package/generated/schema/approval.executed.json +125 -0
  299. package/generated/schema/approval.request.json +279 -0
  300. package/generated/schema/approval.resolved.json +162 -0
  301. package/generated/schema/approval.routed.json +185 -0
  302. package/generated/schema/artifact.create.json +206 -0
  303. package/generated/schema/attachment.fetched.json +114 -0
  304. package/generated/schema/attachment.limits_set.json +136 -0
  305. package/generated/schema/budget.warning.json +152 -0
  306. package/generated/schema/checkpoint.json +111 -0
  307. package/generated/schema/context.compacted.json +124 -0
  308. package/generated/schema/context.usage.json +120 -0
  309. package/generated/schema/exchange.limits_set.json +127 -0
  310. package/generated/schema/exchange.set.json +144 -0
  311. package/generated/schema/feedback.json +173 -0
  312. package/generated/schema/handoff.json +122 -0
  313. package/generated/schema/harness.removed.json +122 -0
  314. package/generated/schema/harness.transferred.json +117 -0
  315. package/generated/schema/hello.json +509 -0
  316. package/generated/schema/join.allowed.json +176 -0
  317. package/generated/schema/join.denied.json +150 -0
  318. package/generated/schema/lane.updated.json +223 -0
  319. package/generated/schema/membership.added.json +153 -0
  320. package/generated/schema/membership.removed.json +126 -0
  321. package/generated/schema/membership.replaced.json +106 -0
  322. package/generated/schema/message.deleted.json +105 -0
  323. package/generated/schema/message.edited.json +107 -0
  324. package/generated/schema/message.handed.json +111 -0
  325. package/generated/schema/message.heard.json +100 -0
  326. package/generated/schema/message.held.json +181 -0
  327. package/generated/schema/message.hidden.json +100 -0
  328. package/generated/schema/message.new.json +1369 -0
  329. package/generated/schema/message.overheard.json +701 -0
  330. package/generated/schema/message.pinned.json +100 -0
  331. package/generated/schema/message.post.json +290 -0
  332. package/generated/schema/message.shown.json +100 -0
  333. package/generated/schema/message.unpinned.json +100 -0
  334. package/generated/schema/person.face_set.json +134 -0
  335. package/generated/schema/person.joined.json +128 -0
  336. package/generated/schema/person.removed.json +133 -0
  337. package/generated/schema/person.renamed.json +114 -0
  338. package/generated/schema/policy.updated.json +277 -0
  339. package/generated/schema/project.changed.json +199 -0
  340. package/generated/schema/question.answered.json +154 -0
  341. package/generated/schema/question.ask.json +194 -0
  342. package/generated/schema/receipt.json +109 -0
  343. package/generated/schema/relay.set.json +99 -0
  344. package/generated/schema/role.changed.json +116 -0
  345. package/generated/schema/run.cancel.json +106 -0
  346. package/generated/schema/run.completed.json +139 -0
  347. package/generated/schema/run.failed.json +135 -0
  348. package/generated/schema/run.pause.json +106 -0
  349. package/generated/schema/run.plan.json +128 -0
  350. package/generated/schema/run.requested.json +309 -0
  351. package/generated/schema/run.resume.json +106 -0
  352. package/generated/schema/run.started.json +142 -0
  353. package/generated/schema/run.status.json +120 -0
  354. package/generated/schema/run.steer.json +163 -0
  355. package/generated/schema/session.ended.json +106 -0
  356. package/generated/schema/session.renamed.json +108 -0
  357. package/generated/schema/session.started.json +116 -0
  358. package/generated/schema/space.claimed.json +107 -0
  359. package/generated/schema/space.created.json +148 -0
  360. package/generated/schema/space.erased.json +129 -0
  361. package/generated/schema/space.lead_set.json +108 -0
  362. package/generated/schema/space.lock_set.json +99 -0
  363. package/generated/schema/space.spend_ceiling_set.json +102 -0
  364. package/generated/schema/space.updated.json +112 -0
  365. package/generated/schema/step.log.json +187 -0
  366. package/generated/schema/task.json +268 -0
  367. package/generated/schema/turn.passed.json +99 -0
  368. package/generated/schema/usage.json +155 -0
  369. package/generated/schema/workspace.renamed.json +107 -0
  370. package/generated/types.ts +4178 -0
  371. package/package.json +38 -3
@@ -0,0 +1,499 @@
1
+ /**
2
+ * A room's project (ADR 0220): one git repository per room, which Chips holds and serves over
3
+ * git's own smart HTTP. Every agent in the room works in a clone of its own, and its bridge does
4
+ * the git (ADR 0221); a person's device clones it with a token that holds for ten minutes.
5
+ *
6
+ * - **One branch.** `main`, which a push may move forward and never rewrite or delete.
7
+ * - **Who.** A harness, for one of its agents in the room, named in `chips-actor`; or a person in
8
+ * the room, with a project token from `POST /v1/spaces/:id/project/token`.
9
+ * - **What it won't keep.** A secrets file (`.env`, `.env.local`), anything that looks like a
10
+ * key, and a file over the workspace's cap for files.
11
+ *
12
+ * The server, the conformance fake and the SDK name the same paths and the same header, and look
13
+ * for secrets the same way, so those live here.
14
+ */
15
+ import { z } from "zod";
16
+ import { isoTimestamp } from "./primitives.js";
17
+ /** The one branch a room's project has. */
18
+ export const PROJECT_BRANCH = "main";
19
+ /** Where a room's project is served: what a clone's remote URL ends in. */
20
+ export function projectPath(spaceId) {
21
+ return `/v1/spaces/${spaceId}/project.git`;
22
+ }
23
+ /**
24
+ * The room a request to its project names, and what follows `project.git`; nothing when the path
25
+ * is not a project's.
26
+ */
27
+ export function projectRequest(path) {
28
+ const match = /^\/v1\/spaces\/(spc_[0-7][0-9A-HJKMNP-TV-Z]{25})\/project\.git(\/.*)?$/.exec(path);
29
+ if (match === null)
30
+ return undefined;
31
+ return { spaceId: match[1] ?? "", rest: match[2] ?? "/" };
32
+ }
33
+ /** The header a harness names the agent it fetches or pushes for with (ADR 0087). */
34
+ export const PROJECT_ACTOR_HEADER = "chips-actor";
35
+ /** The oldest git that takes a token through its environment (`GIT_CONFIG_COUNT`). */
36
+ export const PROJECT_GIT_VERSION = "2.31.0";
37
+ /** How long a person's project token holds. */
38
+ export const PROJECT_TOKEN_TTL_SECONDS = 600;
39
+ /** The prefix a project token wears, as a harness token wears `chips_at_`. */
40
+ export const PROJECT_TOKEN_PREFIX = "chips_pt_";
41
+ /** `POST /v1/spaces/:id/project/token`'s answer. */
42
+ export const projectToken = z.object({
43
+ token: z
44
+ .string()
45
+ .startsWith(PROJECT_TOKEN_PREFIX)
46
+ .describe("Good for this room's project only, until `expires_at`: as a bearer token, or as the password of git's credential helper."),
47
+ expires_at: isoTimestamp,
48
+ path: z
49
+ .string()
50
+ .describe("The project's path on this server, which the device puts its own address in front of."),
51
+ });
52
+ /**
53
+ * `POST /v1/spaces/:id/project/folder/open`'s answer (ADR 0225): how many of the person's own
54
+ * Macs were sent `folder.open`. Nought means Chips for Mac isn't open anywhere.
55
+ */
56
+ export const projectFolderOpenAnswer = z.object({
57
+ macs: z.int().nonnegative().describe("How many of the person's Macs were asked."),
58
+ opened_app: z
59
+ .literal(true)
60
+ .optional()
61
+ .describe("No Chips for Mac of theirs was open, so the server opened the one on its own machine and waited for it (ADR 0227)."),
62
+ });
63
+ /**
64
+ * The agents' and Chips's own folder at the project's top (ADR 0227): the start page and the run
65
+ * file. Files leaves it out, and Finder hides it as it hides `.git`.
66
+ */
67
+ export const CHIPS_FOLDER = ".chips";
68
+ /** The file that says how the project runs on the person's Mac (ADRs 0226, 0227). */
69
+ export const RUN_FILE = ".chips/run.json";
70
+ /** Where the run file was kept before ADR 0227, read when there is no `RUN_FILE`. */
71
+ export const RUN_FILE_BEFORE = "chips.json";
72
+ /** The page that links to the documents worth seeing, which Universe opens (ADR 0227). */
73
+ export const START_PAGE = ".chips/index.html";
74
+ /**
75
+ * What a link to a file of the project becomes when chipsd builds a page (ADR 0227): this, then the
76
+ * path, encoded as a URI component. The phone's page view opens the file over the page; in a frame,
77
+ * the builder's script hands the path to the window as `{chipsFile: path}`.
78
+ */
79
+ export const FILE_LINK = "chips-file:";
80
+ /** The longest command Run runs. */
81
+ const RECIPE_MOST = 500;
82
+ /** The longest a press names: setup, run and what it opens, as `folder.run` carries it. */
83
+ const COMMAND_MOST = 1100;
84
+ /**
85
+ * The run file's recipe, or why it isn't one: the Mac reads it before it runs anything, and the
86
+ * phone and the web read it to show what Run does. `opens` is never somewhere on the internet.
87
+ * `file` is the run file it was read from, which its words name.
88
+ */
89
+ export function runRecipe(text, file = RUN_FILE) {
90
+ let said;
91
+ try {
92
+ said = JSON.parse(text);
93
+ }
94
+ catch {
95
+ return { why: `${file} isn't JSON.` };
96
+ }
97
+ const fields = (typeof said === "object" && said !== null ? said : {});
98
+ const field = (key) => {
99
+ const value = fields[key];
100
+ return typeof value === "string" && value.trim() !== "" ? value.trim() : undefined;
101
+ };
102
+ const run = field("run");
103
+ const opens = field("opens");
104
+ const setup = field("setup");
105
+ const why = whyNot(file, run, opens, setup);
106
+ if (why !== undefined)
107
+ return { why };
108
+ if (saysTooMuch({ run, opens, setup }))
109
+ return { why: `${file} says more than Chips runs.` };
110
+ if (opens !== undefined && !opensOnTheMac(opens)) {
111
+ return {
112
+ why: `${file} opens ${opens}, and Run opens only the Mac's own addresses and the project's files.`,
113
+ };
114
+ }
115
+ if (opens !== undefined && opensAProgram(opens)) {
116
+ return {
117
+ why: `${file} opens ${opens}, which the Mac would run as a program. Say how to start it as "run", where you see what it does.`,
118
+ };
119
+ }
120
+ return {
121
+ ...(run === undefined ? {} : { run }),
122
+ ...(opens === undefined ? {} : { opens }),
123
+ ...(setup === undefined ? {} : { setup }),
124
+ };
125
+ }
126
+ /** Whether a recipe is longer than Run runs, a part of it or the whole of what a press names. */
127
+ function saysTooMuch(recipe) {
128
+ const { run, opens, setup } = recipe;
129
+ if ([run, opens, setup].some((each) => (each?.length ?? 0) > RECIPE_MOST))
130
+ return true;
131
+ return commandOf(recipe).length > COMMAND_MOST;
132
+ }
133
+ /** Why a recipe can't be one before its lengths and its address are looked at: nothing to start, or elsewhere. */
134
+ function whyNot(file, run, opens, setup) {
135
+ return startless(file, run, opens, setup) ?? leavesFolder(file, run, setup);
136
+ }
137
+ /**
138
+ * Why a recipe that runs something outside the project's folder can't be one: a `cd` or `pushd`
139
+ * anywhere but into it, or a path in a home folder on this Mac. What it runs belongs in the
140
+ * project, so it runs on any Mac that has the project and is what the project holds (the game of
141
+ * life sim, 24 October 2026: its run file went into its agent's own workspace, and the project
142
+ * held nothing but the run file).
143
+ */
144
+ function leavesFolder(file, run, setup) {
145
+ const away = [setup, run].map((each) => (each === undefined ? undefined : outsideOf(each)));
146
+ const at = away.find((each) => each !== undefined);
147
+ if (at === undefined)
148
+ return undefined;
149
+ return `${file} uses ${at}, outside the project's folder. Ask the agents to put what it runs in the project.`;
150
+ }
151
+ /** A place a command reaches outside the folder it runs in, or nothing. */
152
+ function outsideOf(command) {
153
+ for (const [, to = ""] of command.matchAll(CD)) {
154
+ const at = to.replace(/^(["'])(.*)\1$/, "$2");
155
+ if (/^(?:\/|~|\$|\.\.(?:\/|$))/.test(at))
156
+ return at;
157
+ }
158
+ return HOME_PATH.exec(command)?.[1];
159
+ }
160
+ /** `cd` or `pushd` and where to, quoted or not. */
161
+ const CD = /(?:^|[\s;&|(])(?:cd|pushd)\s+("[^"]*"|'[^']*'|[^\s;&|)]+)/g;
162
+ /** A path in a home folder: `~/…`, `$HOME/…`, `/Users/<name>/…`, `/home/<name>/…`. */
163
+ const HOME_PATH = /(?:^|[\s"'=:(])((?:~|\$HOME|\$\{HOME\}|\/Users\/[^/\s"';&|)]+|\/home\/[^/\s"';&|)]+)(?:\/[^\s"';&|)]*)?)/;
164
+ /** Why a recipe with nothing to run can't be one: only a file of the project is opened on its own. */
165
+ function startless(file, run, opens, setup) {
166
+ if (run !== undefined)
167
+ return undefined;
168
+ if (opens === undefined)
169
+ return `${file} doesn't say what to run or open.`;
170
+ if (/^https?:\/\//i.test(opens))
171
+ return `${file} opens ${opens} but doesn't say what to run.`;
172
+ if (setup !== undefined)
173
+ return `${file} has a setup but nothing to run.`;
174
+ return undefined;
175
+ }
176
+ /**
177
+ * What a press runs, as the Mac compares it with its folder's run file: setup, then run, then
178
+ * `open` and what it opens. What it opens is part of it, so a run file that changed only where it
179
+ * opens is shown again before it runs (SEC-46).
180
+ */
181
+ export function commandOf(recipe) {
182
+ const opens = recipe.opens === undefined ? undefined : `open ${recipe.opens}`;
183
+ return [recipe.setup, recipe.run, opens].filter((line) => line !== undefined).join("\n");
184
+ }
185
+ /**
186
+ * Files the Mac runs when it opens them: an app, a script Terminal or a launcher runs, an installer,
187
+ * a link elsewhere. A document, a picture or a page opens in its app; these start only as `run`.
188
+ */
189
+ const PROGRAM = /\.(?:app|command|tool|sh|zsh|bash|csh|ksh|py|rb|pl|jar|pkg|mpkg|dmg|terminal|workflow|action|applescript|scpt|scptd|webloc|inetloc|fileloc)$/i;
190
+ /**
191
+ * Whether opening a path runs a program, by its last part once `.`, `..` and slashes are settled
192
+ * as the Mac settles them: `play.command/.` is `play.command` (SEC-46). The Mac asks again of the
193
+ * file it opens, after links.
194
+ */
195
+ export function opensAProgram(path) {
196
+ const parts = [];
197
+ for (const part of path.split("/")) {
198
+ if (part === "..")
199
+ parts.pop();
200
+ else if (part !== "" && part !== ".")
201
+ parts.push(part);
202
+ }
203
+ return PROGRAM.test(parts.at(-1) ?? "");
204
+ }
205
+ /** An address on the Mac itself, or a file in the project. */
206
+ function opensOnTheMac(opens) {
207
+ if (/^[a-z][a-z0-9+.-]*:/i.test(opens)) {
208
+ if (!/^https?:\/\//i.test(opens))
209
+ return false;
210
+ try {
211
+ const { hostname } = new URL(opens);
212
+ return hostname === "localhost" || hostname === "127.0.0.1" || hostname === "[::1]";
213
+ }
214
+ catch {
215
+ return false;
216
+ }
217
+ }
218
+ return !opens.startsWith("/") && !opens.split(/[\\/]/).includes("..");
219
+ }
220
+ /**
221
+ * What Run shows of `opens`: `localhost:8000`, or the file's name. An address of this Mac's own,
222
+ * `127.0.0.1` or `[::1]`, which Run opens to reach exactly where a program listens (ADR 0230),
223
+ * reads as `localhost`.
224
+ */
225
+ export function opensShown(opens) {
226
+ return opens
227
+ .replace(/^https?:\/\//i, "")
228
+ .replace(/^(?:127\.0\.0\.1|\[::1\])(?=[:/]|$)/, "localhost")
229
+ .replace(/\/$/, "");
230
+ }
231
+ /** A run of the room's project on the person's Mac (ADR 0226), as that Mac tells it. */
232
+ export const projectRun = z.object({
233
+ state: z
234
+ .enum(["never", "starting", "running", "ended", "failed", "stopped", "opened"])
235
+ .describe("Never run on that Mac; starting (setup, or waiting for it to answer); running; ended by itself; failed; stopped by the person; or opened, for pages that need no starting."),
236
+ command: z
237
+ .string()
238
+ .max(COMMAND_MOST)
239
+ .optional()
240
+ .describe("What ran: `setup`, `run` and `open` with what it opens, a line each; the bar compares it with the recipe's."),
241
+ commit: z
242
+ .string()
243
+ .regex(/^[0-9a-f]{40}(?:[0-9a-f]{24})?$/)
244
+ .optional()
245
+ .describe("The room's `main` the folder had when it started, so the bar can name who changed the files since (SEC-40)."),
246
+ since: isoTimestamp.optional(),
247
+ ended: isoTimestamp.optional(),
248
+ code: z.int().optional().describe("How it ended, as its shell said."),
249
+ opened: z.string().max(600).optional().describe("What it opened, once it answered."),
250
+ lines: z
251
+ .array(z.string().max(400))
252
+ .max(20)
253
+ .optional()
254
+ .describe("Its last lines, when it ended, or while it runs and something went wrong."),
255
+ why: z
256
+ .string()
257
+ .max(400)
258
+ .optional()
259
+ .describe("Why the Mac didn't run it when it was last asked, in its words: no run file, or a different one."),
260
+ trouble: z
261
+ .string()
262
+ .max(400)
263
+ .optional()
264
+ .describe("What went wrong with the run itself, in plain words (ADR 0230): a port in use, a program the Mac doesn't have, nothing answering, the browser refusing its address."),
265
+ });
266
+ /** A run as the server holds it for the person's other devices: which Mac said it, and when. */
267
+ export const heldRun = projectRun.extend({
268
+ mac: z.string().min(1).max(120).describe("The name of the Mac it runs on."),
269
+ said_at: isoTimestamp,
270
+ });
271
+ /**
272
+ * `GET /v1/spaces/:id/project/run`'s answer: how the person's last run of the room stands, as
273
+ * their Mac last said, and how many of their Macs are open now to run or stop it.
274
+ */
275
+ export const projectRunAnswer = z.object({
276
+ run: heldRun.optional(),
277
+ macs: z.int().nonnegative(),
278
+ });
279
+ /** A git object id: SHA-1, or SHA-256 for a repository made with it. */
280
+ export const commitId = z
281
+ .string()
282
+ .regex(/^[0-9a-f]{40}(?:[0-9a-f]{24})?$/)
283
+ .describe("A commit, by its full git object id.");
284
+ /** The most files `project.changed` names; the rest are counted. */
285
+ export const PROJECT_CHANGED_FILES = 200;
286
+ export const projectChangedFile = z.object({
287
+ path: z.string().min(1).max(1024).describe("Its path in the project, with `/` between folders."),
288
+ added: z.int().nonnegative().nullable().describe("Lines added; `null` for a binary file."),
289
+ removed: z.int().nonnegative().nullable().describe("Lines removed; `null` for a binary file."),
290
+ });
291
+ export const projectChangedPayload = z.object({
292
+ by: z
293
+ .string()
294
+ .min(1)
295
+ .max(120)
296
+ .describe("Who pushed: the agent a harness named, or the person. Recorded by Chips."),
297
+ before: commitId.nullable().describe("Where `main` was, or `null` for the project's first push."),
298
+ after: commitId.describe("Where `main` is now."),
299
+ commits: z.int().positive().describe("How many commits the push added to `main`."),
300
+ message: z.string().max(300).describe("The first line of the newest commit's message."),
301
+ files: z
302
+ .array(projectChangedFile)
303
+ .max(PROJECT_CHANGED_FILES)
304
+ .describe("What changed between `before` and `after`, in path order."),
305
+ more_files: z.int().positive().optional().describe("How many more files changed than are named."),
306
+ file_count: z
307
+ .int()
308
+ .nonnegative()
309
+ .optional()
310
+ .describe("How many files `main` has now, for the room sheet's Project tile (ADR 0222)."),
311
+ undoes: commitId
312
+ .optional()
313
+ .describe("The change this one takes back, when it is a person's Undo, or Put it back's Undo of an Undo (ADR 0222)."),
314
+ });
315
+ /**
316
+ * A name that says a file holds secrets, `.env`, `.env.local` and the like, and the names of the
317
+ * examples people commit, `.env.example`, `.env.sample` and `.env.template`, which don't. Sources,
318
+ * as `SECRET_SHAPES` are.
319
+ */
320
+ export const SECRETS_FILE = {
321
+ source: "^\\.env(?:\\..+)?$",
322
+ unless: "^\\.env\\.(?:example|sample|template)$",
323
+ };
324
+ const SECRETS_NAME = new RegExp(SECRETS_FILE.source);
325
+ const EXAMPLE_NAME = new RegExp(SECRETS_FILE.unless);
326
+ /** Whether a file's name says it holds secrets, wherever it is in the project. */
327
+ export function isSecretsFile(path) {
328
+ const name = path.split("/").pop() ?? path;
329
+ return SECRETS_NAME.test(name) && !EXAMPLE_NAME.test(name);
330
+ }
331
+ /**
332
+ * What a key looks like, by whose it is: the shapes a push is refused for. Sources, not
333
+ * expressions, since the server's check runs in git's hook, a process of its own.
334
+ */
335
+ export const SECRET_SHAPES = [
336
+ { what: "a Chips token", source: "chips_(?:at|inv|j|pt)_[A-Za-z0-9_-]{20,}" },
337
+ // `sk-` begins a word, so a link's words ("…/elon-musk-terafab-project-…") are never a key.
338
+ { what: "an Anthropic key", source: "\\bsk-ant-[A-Za-z0-9_-]{20,}" },
339
+ { what: "an OpenAI key", source: "\\bsk-(?:proj-|svcacct-|admin-)?[A-Za-z0-9_-]{40,}" },
340
+ { what: "an AWS access key", source: "\\b(?:AKIA|ASIA)[0-9A-Z]{16}\\b" },
341
+ {
342
+ what: "a GitHub token",
343
+ source: "\\b(?:gh[pousr]_[A-Za-z0-9]{36,}|github_pat_[A-Za-z0-9_]{60,})",
344
+ },
345
+ { what: "a private key", source: "-----BEGIN (?:[A-Z]+ )*PRIVATE KEY-----" },
346
+ ];
347
+ const SHAPES = SECRET_SHAPES.map((shape) => ({
348
+ what: shape.what,
349
+ pattern: new RegExp(shape.source),
350
+ }));
351
+ /** Whose key a file's words hold, by the first shape they match, or nothing. */
352
+ export function secretIn(text) {
353
+ return SHAPES.find((shape) => shape.pattern.test(text))?.what;
354
+ }
355
+ /**
356
+ * What an agent's copy never commits, written into the copy's own `info/exclude` (ADR 0221): what
357
+ * a build or a package manager makes, what macOS leaves, and secrets files, but not their examples.
358
+ */
359
+ export const PROJECT_LEAVE_OUT = [
360
+ "node_modules/",
361
+ ".venv/",
362
+ "__pycache__/",
363
+ "dist/",
364
+ "build/",
365
+ ".DS_Store",
366
+ ".env",
367
+ ".env.*",
368
+ "!.env.example",
369
+ "!.env.sample",
370
+ "!.env.template",
371
+ ];
372
+ /** `a, b and c`, or the first six and how many more. */
373
+ export function namesInWords(names) {
374
+ if (names.length <= 1)
375
+ return names[0] ?? "";
376
+ if (names.length > 6)
377
+ return `${names.slice(0, 6).join(", ")} and ${names.length - 6} more`;
378
+ return `${names.slice(0, -1).join(", ")} and ${names[names.length - 1]}`;
379
+ }
380
+ /**
381
+ * The note an agent's turn opens its project with: where its copy is and that the bridge does the
382
+ * git, what others changed, a clash to settle or a key to take out, and, in a room with other
383
+ * agents, how to share the work. Its facts, then its asks (ADR 0250).
384
+ */
385
+ export function renderProjectNote(facts, options) {
386
+ return `${renderProjectFacts(facts)}\n${renderProjectAsks(facts, options)}`;
387
+ }
388
+ /**
389
+ * What a turn is told of its copy of the project (ADR 0221): where it is, what others changed, and
390
+ * a clash to settle or a key to take out. Said with every turn.
391
+ */
392
+ export function renderProjectFacts(facts) {
393
+ const files = `${facts.files} file${facts.files === 1 ? "" : "s"}`;
394
+ const lines = [
395
+ `The space's project is a git repository. Your copy is ${facts.folder} (${files}), ${facts.trouble === undefined ? "brought up to date just now" : "not brought up to date"}.`,
396
+ ];
397
+ if (facts.changed.length > 0) {
398
+ const by = facts.by.length > 0 ? `, by ${namesInWords(facts.by)}` : "";
399
+ lines.push(`Changed since your last turn: ${namesInWords(facts.changed)}${by}.`);
400
+ }
401
+ if (facts.trouble !== undefined)
402
+ lines.push(`It couldn't be: ${facts.trouble}`);
403
+ if (facts.clashes.length > 0) {
404
+ const whose = facts.clashedWith.length > 0 ? `${namesInWords(facts.clashedWith)}'s` : "another change";
405
+ lines.push(`Your last change to ${namesInWords(facts.clashes)} clashed with ${whose}, which reached the space first. Both sides are in those files now: yours between "<<<<<<< yours" and "=======", theirs from there to the ">>>>>>>" line that names them. Settle each, keeping what both meant, and take the marks out. Nothing of yours is sent until they're gone.`);
406
+ }
407
+ for (const key of facts.keys) {
408
+ lines.push(`${key.path} holds what looks like ${key.what}, so your last change wasn't sent: take it out and read it from outside the project.`);
409
+ }
410
+ return lines.join("\n");
411
+ }
412
+ /**
413
+ * What the note asks of every turn: where to work, and how, for the room and the files it has. The
414
+ * same from turn to turn while the project and the room keep their shape, so a session that keeps
415
+ * its earlier turns may be told them once (ADR 0250).
416
+ */
417
+ export function renderProjectAsks(facts, options) {
418
+ const lines = [
419
+ "Work on the project in that folder and leave git to Chips: when your turn ends, what you changed is committed under your name and sent to everyone here. Keep scratch work outside it.",
420
+ // Sent with the answer too, a project's file became a room file of its own, with versions of
421
+ // its own, and the agents of a room argued over which copy was current (Phase 8, Run D).
422
+ "Everyone here sees the project's files, so don't send them with your answer as well.",
423
+ ];
424
+ if (options.othersInRoom) {
425
+ lines.push("Split the work by file where you can. Changes to different parts of a file are merged, and a clash goes back to whoever sent second.",
426
+ // Agents whose files must agree each renamed theirs to match the other's at once, so the
427
+ // names crossed back and forth (Phase 8, AP-7): the project's history says who keeps theirs.
428
+ "When your file and another's use different names for the same thing, the one that reached the project first keeps its names, and the other changes its names to match.");
429
+ }
430
+ // Universe opens what the space made (ADR 0227): its documents in Chips, its program on the Mac.
431
+ lines.push("When what you make is to be read (pages, PDFs, pictures), keep a start page at .chips/index.html that links to the documents worth seeing (its links start ../), with the documents themselves at the top or in folders of their own, and bring it up to date whenever you add, rename or replace one. Chips opens it in the app, and its links open there too. One document needs no start page.", 'When what you make has to run on the person\'s Mac (a server, a script, an app), keep .chips/run.json so Run in Chips can start it from the project\'s folder: {"run": "the one shell command that starts it", "opens": "http://localhost:<port>, to open once it answers", "setup": "a command run first when it changes, like npm install"}. Have it print the address it listens on, like http://localhost:4173, which is what Run opens; "opens" is for a program that prints none. Everything it runs belongs in the project: Run refuses a command that goes anywhere outside the project\'s folder (a cd elsewhere, a path in a home folder). Start an app by its own program rather than with open, so Stop can close it, and leave starting it to Run rather than starting it yourself. Leave out what it doesn\'t need, and check it works in your copy before you say it does.');
432
+ if (facts.markdown)
433
+ lines.push("In Markdown, put each sentence on a line of its own.");
434
+ if (facts.pages === true) {
435
+ lines.push("A page opens in Chips as one document: name every file it needs in its tags and imports (<link>, <script src>, <img src>, import), since it can't fetch files while it runs.");
436
+ }
437
+ return lines.join("\n");
438
+ }
439
+ /** What a file of the project is, by its name's extension (ADR 0222): how a client opens it. */
440
+ const PROJECT_FILE_TYPES = {
441
+ html: "text/html",
442
+ htm: "text/html",
443
+ md: "text/markdown",
444
+ markdown: "text/markdown",
445
+ txt: "text/plain",
446
+ csv: "text/csv",
447
+ css: "text/css",
448
+ js: "text/javascript",
449
+ mjs: "text/javascript",
450
+ json: "application/json",
451
+ svg: "image/svg+xml",
452
+ png: "image/png",
453
+ jpg: "image/jpeg",
454
+ jpeg: "image/jpeg",
455
+ gif: "image/gif",
456
+ webp: "image/webp",
457
+ pdf: "application/pdf",
458
+ mp4: "video/mp4",
459
+ mov: "video/quicktime",
460
+ mp3: "audio/mpeg",
461
+ wav: "audio/wav",
462
+ };
463
+ /** Code and other words that open as plain text. */
464
+ const PROJECT_TEXT = new Set([
465
+ "ts",
466
+ "tsx",
467
+ "jsx",
468
+ "py",
469
+ "rb",
470
+ "go",
471
+ "rs",
472
+ "java",
473
+ "kt",
474
+ "swift",
475
+ "c",
476
+ "h",
477
+ "cpp",
478
+ "sh",
479
+ "yml",
480
+ "yaml",
481
+ "toml",
482
+ "ini",
483
+ "xml",
484
+ "sql",
485
+ "gitignore",
486
+ "env",
487
+ ]);
488
+ /** A project file's media type, by its name: `text/plain` for code, `application/octet-stream` for the rest. */
489
+ export function projectFileType(path) {
490
+ const name = path.split("/").pop() ?? path;
491
+ const extension = name.includes(".") ? (name.split(".").pop() ?? "").toLowerCase() : "";
492
+ return (PROJECT_FILE_TYPES[extension] ??
493
+ (PROJECT_TEXT.has(extension) ? "text/plain" : "application/octet-stream"));
494
+ }
495
+ /** Whose a commit is, from the email Chips signs it with: an agent's or a person's id, or nothing. */
496
+ export function committerId(email) {
497
+ return /^((?:agt|usr|hrn)_[0-9A-Za-z]+)@(?:agents|people)\.chips\.invalid$/.exec(email)?.[1];
498
+ }
499
+ //# sourceMappingURL=project.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project.js","sourceRoot":"","sources":["../../src/project.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * What a `Range` header asks of an attachment's bytes (RFC 9110 §14), for
3
+ * `GET /v1/attachments/:id` (ADR 0058). A player seeks by asking for a run of the file, and
4
+ * AVPlayer will not start a video it cannot ask a run of; the server answers `206` with that run.
5
+ *
6
+ * One run, in bytes: a first and a last byte (`bytes=0-499`), a first byte and the rest
7
+ * (`bytes=500-`), or the last so many (`bytes=-500`). A last byte past the end means the end. A
8
+ * header this does not read — another unit, several runs, a last byte before the first — is
9
+ * ignored and the whole file is served, which the standard allows. A run that starts past the end,
10
+ * or asks for the last nought bytes, cannot be served: `416`.
11
+ *
12
+ * Here rather than in the server because the conformance kit's stand-in answers the same route
13
+ * and must answer it the same way.
14
+ */
15
+ /** What to serve for a `Range` header, over a file of so many bytes. */
16
+ export type RangeAnswer = {
17
+ readonly kind: "whole";
18
+ }
19
+ /** From `start` to `end`, both included, as `Content-Range` counts them. */
20
+ | {
21
+ readonly kind: "part";
22
+ readonly start: number;
23
+ readonly end: number;
24
+ } | {
25
+ readonly kind: "unsatisfiable";
26
+ };
27
+ /** The run a `Range` header asks for, of a file `size` bytes long. */
28
+ export declare function byteRange(header: string | null | undefined, size: number): RangeAnswer;
29
+ /** `Content-Range` for a part of a file, or for a range that could not be served. */
30
+ export declare function contentRange(answer: RangeAnswer, size: number): string | undefined;
31
+ //# sourceMappingURL=ranges.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ranges.d.ts","sourceRoot":"","sources":["../../src/ranges.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,wEAAwE;AACxE,MAAM,MAAM,WAAW,GACnB;IAAE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAA;CAAE;AAC5B,4EAA4E;GAC1E;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GACvE;IAAE,QAAQ,CAAC,IAAI,EAAE,eAAe,CAAA;CAAE,CAAC;AAQvC,sEAAsE;AACtE,wBAAgB,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAAE,IAAI,EAAE,MAAM,GAAG,WAAW,CAKtF;AAgBD,qFAAqF;AACrF,wBAAgB,YAAY,CAAC,MAAM,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAIlF"}
@@ -0,0 +1,51 @@
1
+ /**
2
+ * What a `Range` header asks of an attachment's bytes (RFC 9110 §14), for
3
+ * `GET /v1/attachments/:id` (ADR 0058). A player seeks by asking for a run of the file, and
4
+ * AVPlayer will not start a video it cannot ask a run of; the server answers `206` with that run.
5
+ *
6
+ * One run, in bytes: a first and a last byte (`bytes=0-499`), a first byte and the rest
7
+ * (`bytes=500-`), or the last so many (`bytes=-500`). A last byte past the end means the end. A
8
+ * header this does not read — another unit, several runs, a last byte before the first — is
9
+ * ignored and the whole file is served, which the standard allows. A run that starts past the end,
10
+ * or asks for the last nought bytes, cannot be served: `416`.
11
+ *
12
+ * Here rather than in the server because the conformance kit's stand-in answers the same route
13
+ * and must answer it the same way.
14
+ */
15
+ const WHOLE = { kind: "whole" };
16
+ const UNSATISFIABLE = { kind: "unsatisfiable" };
17
+ /** `bytes=first-last`, either side of the dash possibly empty; the unit is case-insensitive. */
18
+ const ONE_RUN = /^bytes[ \t]*=[ \t]*(\d*)[ \t]*-[ \t]*(\d*)[ \t]*$/i;
19
+ /** The run a `Range` header asks for, of a file `size` bytes long. */
20
+ export function byteRange(header, size) {
21
+ const run = header === null || header === undefined ? null : ONE_RUN.exec(header.trim());
22
+ if (run === null)
23
+ return WHOLE;
24
+ const [, first = "", last = ""] = run;
25
+ return first === "" ? lastBytes(last, size) : fromByte(Number(first), last, size);
26
+ }
27
+ /** `bytes=-500`: the last so many. Asking for none of them is asking for nothing that can be served. */
28
+ function lastBytes(count, size) {
29
+ if (count === "")
30
+ return WHOLE;
31
+ if (Number(count) === 0 || size === 0)
32
+ return UNSATISFIABLE;
33
+ return { kind: "part", start: Math.max(0, size - Number(count)), end: size - 1 };
34
+ }
35
+ /** `bytes=500-999`, or `bytes=500-` for the rest. A last byte past the end is the end. */
36
+ function fromByte(start, last, size) {
37
+ if (last !== "" && Number(last) < start)
38
+ return WHOLE;
39
+ if (start >= size)
40
+ return UNSATISFIABLE;
41
+ return { kind: "part", start, end: last === "" ? size - 1 : Math.min(Number(last), size - 1) };
42
+ }
43
+ /** `Content-Range` for a part of a file, or for a range that could not be served. */
44
+ export function contentRange(answer, size) {
45
+ if (answer.kind === "part")
46
+ return `bytes ${answer.start}-${answer.end}/${size}`;
47
+ if (answer.kind === "unsatisfiable")
48
+ return `bytes */${size}`;
49
+ return undefined;
50
+ }
51
+ //# sourceMappingURL=ranges.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ranges.js","sourceRoot":"","sources":["../../src/ranges.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AASH,MAAM,KAAK,GAAgB,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;AAC7C,MAAM,aAAa,GAAgB,EAAE,IAAI,EAAE,eAAe,EAAE,CAAC;AAE7D,gGAAgG;AAChG,MAAM,OAAO,GAAG,oDAAoD,CAAC;AAErE,sEAAsE;AACtE,MAAM,UAAU,SAAS,CAAC,MAAiC,EAAE,IAAY;IACvE,MAAM,GAAG,GAAG,MAAM,KAAK,IAAI,IAAI,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;IACzF,IAAI,GAAG,KAAK,IAAI;QAAE,OAAO,KAAK,CAAC;IAC/B,MAAM,CAAC,EAAE,KAAK,GAAG,EAAE,EAAE,IAAI,GAAG,EAAE,CAAC,GAAG,GAAG,CAAC;IACtC,OAAO,KAAK,KAAK,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;AACpF,CAAC;AAED,wGAAwG;AACxG,SAAS,SAAS,CAAC,KAAa,EAAE,IAAY;IAC5C,IAAI,KAAK,KAAK,EAAE;QAAE,OAAO,KAAK,CAAC;IAC/B,IAAI,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC;QAAE,OAAO,aAAa,CAAC;IAC5D,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,EAAE,IAAI,GAAG,CAAC,EAAE,CAAC;AACnF,CAAC;AAED,0FAA0F;AAC1F,SAAS,QAAQ,CAAC,KAAa,EAAE,IAAY,EAAE,IAAY;IACzD,IAAI,IAAI,KAAK,EAAE,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,KAAK;QAAE,OAAO,KAAK,CAAC;IACtD,IAAI,KAAK,IAAI,IAAI;QAAE,OAAO,aAAa,CAAC;IACxC,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,IAAI,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,GAAG,CAAC,CAAC,EAAE,CAAC;AACjG,CAAC;AAED,qFAAqF;AACrF,MAAM,UAAU,YAAY,CAAC,MAAmB,EAAE,IAAY;IAC5D,IAAI,MAAM,CAAC,IAAI,KAAK,MAAM;QAAE,OAAO,SAAS,MAAM,CAAC,KAAK,IAAI,MAAM,CAAC,GAAG,IAAI,IAAI,EAAE,CAAC;IACjF,IAAI,MAAM,CAAC,IAAI,KAAK,eAAe;QAAE,OAAO,WAAW,IAAI,EAAE,CAAC;IAC9D,OAAO,SAAS,CAAC;AACnB,CAAC"}