iterate 0.3.0 → 0.4.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 (241) hide show
  1. package/README.md +164 -82
  2. package/dist/{next/api.d.ts → api.d.ts} +197 -33
  3. package/dist/{next/app-server.d.ts → app-server.d.ts} +7 -0
  4. package/dist/{next/app-server.mjs → app-server.mjs} +17 -15
  5. package/dist/app-server.mjs.map +1 -0
  6. package/dist/{next/app-session.mjs → app-session.mjs} +12 -15
  7. package/dist/app-session.mjs.map +1 -0
  8. package/dist/{next/app.mjs → app.mjs} +53 -14
  9. package/dist/app.mjs.map +1 -0
  10. package/dist/{next/client → client}/live-state.d.ts +11 -11
  11. package/dist/client/oauth.d.ts +17 -0
  12. package/dist/{next/client → client}/react.d.ts +10 -42
  13. package/dist/{next/client → client}/socket.d.ts +1 -0
  14. package/dist/client.mjs +156 -4
  15. package/dist/client.mjs.map +1 -0
  16. package/dist/{next/expression.d.ts → expression.d.ts} +11 -69
  17. package/dist/{next/expression.mjs → expression.mjs} +11 -109
  18. package/dist/expression.mjs.map +1 -0
  19. package/dist/lib-BWr-5mFO.mjs +36 -0
  20. package/dist/lib-BWr-5mFO.mjs.map +1 -0
  21. package/dist/{next/lib.d.ts → lib.d.ts} +16 -2
  22. package/dist/{next/lib.mjs → lib.mjs} +32 -3
  23. package/dist/lib.mjs.map +1 -0
  24. package/dist/node.d.ts +15 -3
  25. package/dist/node.mjs +36 -174
  26. package/dist/node.mjs.map +1 -1
  27. package/dist/{next/oauth-scopes.mjs → oauth-scopes.mjs} +1 -1
  28. package/dist/oauth-scopes.mjs.map +1 -0
  29. package/dist/{next/oauth.mjs → oauth.mjs} +14 -2
  30. package/dist/oauth.mjs.map +1 -0
  31. package/dist/principal.d.ts +8 -0
  32. package/dist/principal.mjs +8 -0
  33. package/dist/principal.mjs.map +1 -0
  34. package/dist/project-ingress.d.ts +58 -0
  35. package/dist/project-ingress.mjs +104 -0
  36. package/dist/project-ingress.mjs.map +1 -0
  37. package/dist/{next/react.mjs → react.mjs} +12 -12
  38. package/dist/react.mjs.map +1 -0
  39. package/dist/sdk/auth.d.ts +25 -0
  40. package/dist/sdk/index.d.ts +155 -0
  41. package/dist/sdk/record-pipelined-steps.d.ts +19 -0
  42. package/dist/sdk.mjs +245 -2
  43. package/dist/sdk.mjs.map +1 -0
  44. package/dist/{next/stream → stream}/processor.d.ts +28 -23
  45. package/dist/{next/stream → stream}/processor.mjs +48 -25
  46. package/dist/stream/processor.mjs.map +1 -0
  47. package/dist/{next/stream → stream}/run.d.ts +9 -6
  48. package/dist/{next/stream → stream}/run.mjs +13 -8
  49. package/dist/stream/run.mjs.map +1 -0
  50. package/dist/stream/test-support.d.ts +45 -0
  51. package/dist/stream/test-support.mjs +196 -0
  52. package/dist/stream/test-support.mjs.map +1 -0
  53. package/package.json +65 -219
  54. package/THIRD_PARTY_NOTICES.md +0 -55
  55. package/bin/iterate.js +0 -94
  56. package/dist/api-url-B6404M82.mjs +0 -17
  57. package/dist/api-url-B6404M82.mjs.map +0 -1
  58. package/dist/app-ref-BipL0feU.mjs +0 -35
  59. package/dist/app-ref-BipL0feU.mjs.map +0 -1
  60. package/dist/app-ref-C1CrgXqX.mjs +0 -7
  61. package/dist/app-ref-C1CrgXqX.mjs.map +0 -1
  62. package/dist/app-ref-DYai_om1.mjs +0 -7
  63. package/dist/app-ref-DYai_om1.mjs.map +0 -1
  64. package/dist/cli-D0c-pDL_.mjs +0 -1010
  65. package/dist/cli-D0c-pDL_.mjs.map +0 -1
  66. package/dist/client.d.ts +0 -3
  67. package/dist/cloudflare-BTm90gQ4.mjs +0 -951
  68. package/dist/cloudflare-BTm90gQ4.mjs.map +0 -1
  69. package/dist/contract-s4FW4eES.mjs +0 -309
  70. package/dist/contract-s4FW4eES.mjs.map +0 -1
  71. package/dist/document-review/index.d.ts +0 -5
  72. package/dist/document-review/types.d.ts +0 -107
  73. package/dist/document-review.mjs +0 -7015
  74. package/dist/document-review.mjs.map +0 -1
  75. package/dist/durable-object-processor-durability-CNsTjAJS.mjs +0 -205
  76. package/dist/durable-object-processor-durability-CNsTjAJS.mjs.map +0 -1
  77. package/dist/idempotency-DleloJNt.mjs +0 -28
  78. package/dist/idempotency-DleloJNt.mjs.map +0 -1
  79. package/dist/index.d.mts +0 -5
  80. package/dist/index.mjs +0 -8
  81. package/dist/index.mjs.map +0 -1
  82. package/dist/itx/api-url.d.ts +0 -6
  83. package/dist/itx/itx-node-client.d.ts +0 -65
  84. package/dist/itx/itx-session.d.ts +0 -215
  85. package/dist/itx/owned-rpc-session.d.ts +0 -14
  86. package/dist/itx/query-client.d.ts +0 -10
  87. package/dist/itx-api.generated.d.ts +0 -6195
  88. package/dist/itx-session-sjud8GiT.mjs +0 -534
  89. package/dist/itx-session-sjud8GiT.mjs.map +0 -1
  90. package/dist/live-state-BJNqOwFw.mjs +0 -299
  91. package/dist/live-state-BJNqOwFw.mjs.map +0 -1
  92. package/dist/next/app-server.mjs.map +0 -1
  93. package/dist/next/app-session.mjs.map +0 -1
  94. package/dist/next/app.mjs.map +0 -1
  95. package/dist/next/client/oauth.d.ts +0 -12
  96. package/dist/next/client.mjs +0 -156
  97. package/dist/next/client.mjs.map +0 -1
  98. package/dist/next/expression.mjs.map +0 -1
  99. package/dist/next/lib.mjs.map +0 -1
  100. package/dist/next/oauth-scopes.mjs.map +0 -1
  101. package/dist/next/oauth.mjs.map +0 -1
  102. package/dist/next/principal.d.ts +0 -64
  103. package/dist/next/principal.mjs +0 -98
  104. package/dist/next/principal.mjs.map +0 -1
  105. package/dist/next/project-ingress.d.ts +0 -37
  106. package/dist/next/project-ingress.mjs +0 -75
  107. package/dist/next/project-ingress.mjs.map +0 -1
  108. package/dist/next/react.mjs.map +0 -1
  109. package/dist/next/sdk/auth.d.ts +0 -5
  110. package/dist/next/sdk/index.d.ts +0 -112
  111. package/dist/next/sdk.mjs +0 -139
  112. package/dist/next/sdk.mjs.map +0 -1
  113. package/dist/next/stream/processor.mjs.map +0 -1
  114. package/dist/next/stream/run.mjs.map +0 -1
  115. package/dist/next-node.d.ts +0 -15
  116. package/dist/next-node.mjs +0 -51
  117. package/dist/next-node.mjs.map +0 -1
  118. package/dist/processor-host-capabilities-BMFH3KTM.mjs +0 -56
  119. package/dist/processor-host-capabilities-BMFH3KTM.mjs.map +0 -1
  120. package/dist/processors/cloudflare.d.ts +0 -3
  121. package/dist/processors/durable-object-processor-durability.d.ts +0 -79
  122. package/dist/processors/event-consumption-metrics.d.ts +0 -82
  123. package/dist/processors/idempotency.d.ts +0 -13
  124. package/dist/processors/index.d.ts +0 -12
  125. package/dist/processors/processor-contracts.d.ts +0 -342
  126. package/dist/processors/processor-facet.d.ts +0 -186
  127. package/dist/processors/processor-host-capabilities.d.ts +0 -60
  128. package/dist/processors/prompt-sections.d.ts +0 -17
  129. package/dist/processors/rpc-types.d.ts +0 -515
  130. package/dist/processors/schemas.d.ts +0 -102
  131. package/dist/processors/stream-handle.d.ts +0 -45
  132. package/dist/processors/stream-processor-keepalive.d.ts +0 -95
  133. package/dist/processors/stream-processor-registry.d.ts +0 -233
  134. package/dist/processors/stream-processor-runner.d.ts +0 -289
  135. package/dist/processors/stream-processor.d.ts +0 -339
  136. package/dist/processors/stream-runtime-metrics.d.ts +0 -107
  137. package/dist/processors/testing.d.ts +0 -302
  138. package/dist/processors-BoNyeBfQ.mjs +0 -10
  139. package/dist/processors-BoNyeBfQ.mjs.map +0 -1
  140. package/dist/processors-cloudflare.mjs +0 -3
  141. package/dist/processors-testing.mjs +0 -435
  142. package/dist/processors-testing.mjs.map +0 -1
  143. package/dist/processors.mjs +0 -52
  144. package/dist/processors.mjs.map +0 -1
  145. package/dist/protocol-DnK_f2m6.mjs +0 -251
  146. package/dist/protocol-DnK_f2m6.mjs.map +0 -1
  147. package/dist/sdk/capnweb/index.d.ts +0 -2
  148. package/dist/sdk/capnweb/live-state/compact.d.ts +0 -5
  149. package/dist/sdk/capnweb/live-state/diff.d.ts +0 -41
  150. package/dist/sdk/capnweb/live-state/engine.d.ts +0 -44
  151. package/dist/sdk/capnweb/live-state/index.d.ts +0 -41
  152. package/dist/sdk/capnweb/live-state/protocol.d.ts +0 -87
  153. package/dist/sdk/capnweb/live-state/retain.d.ts +0 -23
  154. package/dist/sdk/capnweb/live-state/store.d.ts +0 -20
  155. package/dist/sdk/capnweb/live-state/types.d.ts +0 -11
  156. package/dist/sdk/capnweb/react.d.ts +0 -45
  157. package/dist/sdk/capnweb/react.mjs +0 -316
  158. package/dist/sdk/capnweb/react.mjs.map +0 -1
  159. package/dist/sdk/capnweb.mjs +0 -4
  160. package/dist/sdk/itx/react.d.ts +0 -191
  161. package/dist/sdk/itx/react.mjs +0 -383
  162. package/dist/sdk/itx/react.mjs.map +0 -1
  163. package/dist/sdk-DMB-IM11.mjs +0 -933
  164. package/dist/sdk-DMB-IM11.mjs.map +0 -1
  165. package/dist/sdk.d.ts +0 -339
  166. package/dist/serve-itx.d.ts +0 -46
  167. package/dist/starter-apps/flake-dashboard/app-ref.d.ts +0 -31
  168. package/dist/starter-apps/flake-dashboard/configured-worker.mjs +0 -1055
  169. package/dist/starter-apps/flake-dashboard/configured-worker.mjs.map +0 -1
  170. package/dist/starter-apps/flake-dashboard/contract.d.ts +0 -4839
  171. package/dist/starter-apps/flake-dashboard/contract.mjs +0 -2
  172. package/dist/starter-apps/flake-dashboard/index.d.ts +0 -17
  173. package/dist/starter-apps/flake-dashboard/index.mjs +0 -56
  174. package/dist/starter-apps/flake-dashboard/index.mjs.map +0 -1
  175. package/dist/starter-apps/flake-dashboard/worker.d.ts +0 -4607
  176. package/dist/starter-apps/github-ai-linter/ai-linter.d.ts +0 -8914
  177. package/dist/starter-apps/github-ai-linter/configured-worker.mjs +0 -17987
  178. package/dist/starter-apps/github-ai-linter/configured-worker.mjs.map +0 -1
  179. package/dist/starter-apps/github-ai-linter/contract.d.ts +0 -9193
  180. package/dist/starter-apps/github-ai-linter/index.d.ts +0 -10
  181. package/dist/starter-apps/github-ai-linter/index.mjs +0 -36
  182. package/dist/starter-apps/github-ai-linter/index.mjs.map +0 -1
  183. package/dist/starter-apps/github-ai-linter/prompt.d.ts +0 -13
  184. package/dist/starter-apps/github-ai-linter/review-bot.d.ts +0 -808
  185. package/dist/starter-apps/github-ai-linter/rules.d.ts +0 -34
  186. package/dist/starter-apps/github-ai-linter/worker-ref.d.ts +0 -19
  187. package/dist/starter-apps/github-ai-linter/worker.d.ts +0 -19
  188. package/dist/starter-apps/github-ai-linter/worker.mjs +0 -947
  189. package/dist/starter-apps/github-ai-linter/worker.mjs.map +0 -1
  190. package/dist/starter-apps/guestbook/app-ref.d.ts +0 -27
  191. package/dist/starter-apps/guestbook/client.d.ts +0 -7
  192. package/dist/starter-apps/guestbook/client.mjs +0 -59
  193. package/dist/starter-apps/guestbook/configured-worker.mjs +0 -205
  194. package/dist/starter-apps/guestbook/configured-worker.mjs.map +0 -1
  195. package/dist/starter-apps/guestbook/index.d.ts +0 -9
  196. package/dist/starter-apps/guestbook/index.mjs +0 -31
  197. package/dist/starter-apps/guestbook/index.mjs.map +0 -1
  198. package/dist/starter-apps/guestbook/processor.d.ts +0 -2267
  199. package/dist/starter-apps/guestbook/worker.d.ts +0 -26
  200. package/dist/starter-apps/guestbook/worker.mjs +0 -191
  201. package/dist/starter-apps/guestbook/worker.mjs.map +0 -1
  202. package/dist/starter-apps/media/configured-worker.mjs +0 -577
  203. package/dist/starter-apps/media/configured-worker.mjs.map +0 -1
  204. package/dist/starter-apps/media/index.mjs +0 -36
  205. package/dist/starter-apps/media/index.mjs.map +0 -1
  206. package/dist/starter-apps/media/ref.mjs +0 -20
  207. package/dist/starter-apps/media/ref.mjs.map +0 -1
  208. package/dist/starter-apps/media/worker.mjs +0 -579
  209. package/dist/starter-apps/media/worker.mjs.map +0 -1
  210. package/dist/starter-apps/notes/configured-worker.mjs +0 -6134
  211. package/dist/starter-apps/notes/configured-worker.mjs.map +0 -1
  212. package/dist/starter-apps/notes/index.mjs +0 -23
  213. package/dist/starter-apps/notes/index.mjs.map +0 -1
  214. package/dist/starter-apps/notes/ref.mjs +0 -21
  215. package/dist/starter-apps/notes/ref.mjs.map +0 -1
  216. package/dist/starter-apps/notes/worker.mjs +0 -427
  217. package/dist/starter-apps/notes/worker.mjs.map +0 -1
  218. package/dist/starter-apps/todo/client.mjs +0 -59
  219. package/dist/starter-apps/todo/configured-worker.mjs +0 -2864
  220. package/dist/starter-apps/todo/configured-worker.mjs.map +0 -1
  221. package/dist/starter-apps/todo/index.d.ts +0 -8
  222. package/dist/starter-apps/todo/index.mjs +0 -29
  223. package/dist/starter-apps/todo/index.mjs.map +0 -1
  224. package/dist/stream-processor-keepalive-DAQTP6m3.mjs +0 -2082
  225. package/dist/stream-processor-keepalive-DAQTP6m3.mjs.map +0 -1
  226. package/dist/usingCtx-mZx5nsAW.mjs +0 -11800
  227. package/dist/usingCtx-mZx5nsAW.mjs.map +0 -1
  228. package/dist/worker-ref-DZxPDmb_.mjs +0 -390
  229. package/dist/worker-ref-DZxPDmb_.mjs.map +0 -1
  230. package/dist/worker.d.mts +0 -33
  231. package/dist/worker.mjs +0 -18
  232. package/dist/worker.mjs.map +0 -1
  233. package/menubar/Iterate.entitlements +0 -12
  234. package/menubar/Iterate.swift +0 -914
  235. package/menubar/IterateIcon.swift +0 -145
  236. package/menubar/README.md +0 -28
  237. package/menubar/build-menubar-app.sh +0 -59
  238. /package/dist/{next/api.mjs → api.mjs} +0 -0
  239. /package/dist/{next/app-session.d.ts → app-session.d.ts} +0 -0
  240. /package/dist/{next/app.d.ts → app.d.ts} +0 -0
  241. /package/dist/{next/oauth-scopes.d.ts → oauth-scopes.d.ts} +0 -0
@@ -1,390 +0,0 @@
1
- import { h as defineProcessorContract } from "./stream-processor-keepalive-DAQTP6m3.mjs";
2
- import "./processors.mjs";
3
- import { z } from "zod";
4
- //#region src/starter-apps/github-ai-linter/contract.ts
5
- /**
6
- * Keep the vocabulary flat. These names are also copied into the linter
7
- * agent's developer task, so changing one here deliberately breaks an old
8
- * prompt instead of leaving two almost-compatible protocols alive.
9
- *
10
- * The const assertion preserves exact event literals for contract typing. It
11
- * is safe because this object is static vocabulary and is never mutated.
12
- */
13
- const githubAiLinterEventTypes = {
14
- analysisRequested: "events.iterate.com/github-ai-linter/analysis-requested",
15
- diagnosticReported: "events.iterate.com/github-ai-linter/diagnostic-reported",
16
- diagnosticSuppressed: "events.iterate.com/github-ai-linter/diagnostic-suppressed",
17
- analysisSettled: "events.iterate.com/github-ai-linter/analysis-settled",
18
- reviewPublicationRequested: "events.iterate.com/github-ai-linter/review-publication-requested",
19
- reviewPublicationSettled: "events.iterate.com/github-ai-linter/review-publication-settled"
20
- };
21
- const PositiveSafeInteger = z.number().int().positive().max(Number.MAX_SAFE_INTEGER);
22
- const StreamOffset = z.number().int().nonnegative().max(Number.MAX_SAFE_INTEGER);
23
- const RuleName = z.string().regex(/^[a-z0-9-]+(?:\/[a-z0-9-]+)*$/);
24
- const GithubAiLinterRule = z.object({
25
- files: z.array(z.string().min(1)).min(1),
26
- invariant: z.string().min(1),
27
- severity: z.enum(["error", "warning"]),
28
- suggestions: z.enum(["allowed", "forbidden"]).default("allowed")
29
- });
30
- const GithubAiLinterAnalysisRequested = z.object({
31
- appSlug: z.string().min(1),
32
- baseSha: z.string().min(1),
33
- connection: z.string().min(1),
34
- headSha: z.string().min(1),
35
- policyVersion: z.string().min(1),
36
- promptVersion: z.string().min(1),
37
- pullRequestNumber: PositiveSafeInteger,
38
- repository: z.object({
39
- id: PositiveSafeInteger,
40
- owner: z.string().min(1),
41
- repo: z.string().min(1)
42
- }),
43
- rules: z.record(RuleName, GithubAiLinterRule),
44
- rulesCommit: z.string().min(1)
45
- });
46
- const SourceSpanSchema = z.object({
47
- endColumn: PositiveSafeInteger.optional(),
48
- endLine: PositiveSafeInteger,
49
- startColumn: PositiveSafeInteger.optional(),
50
- startLine: PositiveSafeInteger
51
- }).refine(({ endLine, startLine }) => endLine >= startLine, "a source span must end on or after its start line");
52
- const WholeLineSpanSchema = z.object({
53
- endLine: PositiveSafeInteger,
54
- startLine: PositiveSafeInteger
55
- }).refine(({ endLine, startLine }) => endLine >= startLine, "a source span must end on or after its start line");
56
- const GithubAiLinterDiagnostic = z.object({
57
- /**
58
- * Cross-analysis identity. Unlike the GitHub line, this should survive
59
- * nearby edits: rule + filename + a short semantic anchor is the intended
60
- * input. The prompt explicitly forbids line numbers and prose here.
61
- */
62
- diagnosticKey: z.string().min(1).max(500),
63
- filename: z.string().min(1).max(2e3),
64
- fix: z.object({
65
- content: z.string().max(5e4),
66
- /**
67
- * The first slice only publishes human-applied GitHub suggestions.
68
- * A future `fix` kind may authorize an automated branch update, but it
69
- * must be a separate explicit protocol: never reinterpret an archived
70
- * suggestion as permission to mutate code.
71
- */
72
- kind: z.literal("suggestion"),
73
- span: WholeLineSpanSchema
74
- }).optional(),
75
- help: z.string().min(1).max(8e3).optional(),
76
- /**
77
- * Oxlint diagnostics can carry several labels. The first label is the
78
- * primary one and supplies GitHub's inline location in this first version;
79
- * later labels remain structured context for a richer renderer.
80
- */
81
- labels: z.array(z.object({
82
- message: z.string().min(1).max(4e3).optional(),
83
- span: SourceSpanSchema
84
- })).min(1).max(20),
85
- message: z.string().min(1).max(8e3),
86
- ruleName: RuleName,
87
- severity: z.enum(["error", "warning"])
88
- });
89
- const GithubAiLinterDiagnosticReportedPayload = GithubAiLinterDiagnostic.extend({ analysisRequestOffset: StreamOffset });
90
- const GithubAiLinterDiagnosticSuppressedPayload = z.object({
91
- analysisRequestOffset: StreamOffset,
92
- diagnosticOffset: StreamOffset,
93
- directive: z.enum([
94
- "disable",
95
- "disable-line",
96
- "disable-next-line"
97
- ]),
98
- filename: z.string().min(1).max(2e3),
99
- line: PositiveSafeInteger,
100
- reason: z.string().min(1).max(4e3)
101
- });
102
- const GithubAiLinterAssessment = z.object({
103
- summary: z.string().min(1).max(2e4),
104
- verdict: z.enum([
105
- "approve",
106
- "comment",
107
- "request-changes"
108
- ])
109
- });
110
- const GithubAiLinterAnalysisResult = z.discriminatedUnion("status", [
111
- z.object({
112
- assessment: GithubAiLinterAssessment,
113
- status: z.literal("succeeded")
114
- }),
115
- z.object({
116
- reason: z.string().min(1).max(8e3),
117
- status: z.literal("cancelled")
118
- }),
119
- z.object({
120
- error: z.string().min(1).max(8e3),
121
- status: z.literal("failed")
122
- })
123
- ]);
124
- const GithubAiLinterAnalysisSettledPayload = z.object({
125
- analysisRequestOffset: StreamOffset,
126
- result: GithubAiLinterAnalysisResult
127
- });
128
- const PublishedCheckRun = z.object({
129
- id: PositiveSafeInteger,
130
- url: z.string().url()
131
- });
132
- const GithubAiLinterPublicationResult = z.discriminatedUnion("status", [
133
- z.object({
134
- checkRun: PublishedCheckRun,
135
- reason: z.string().min(1).max(8e3),
136
- status: z.literal("skipped")
137
- }),
138
- z.object({
139
- checkRun: PublishedCheckRun.optional(),
140
- reviewId: PositiveSafeInteger,
141
- reviewUrl: z.string().url(),
142
- status: z.literal("succeeded")
143
- }),
144
- z.object({
145
- reason: z.string().min(1).max(8e3),
146
- status: z.literal("cancelled")
147
- }),
148
- z.object({
149
- error: z.string().min(1).max(8e3),
150
- status: z.literal("failed")
151
- })
152
- ]);
153
- const PublicationState = z.discriminatedUnion("status", [
154
- z.object({ status: z.literal("not-requested") }),
155
- z.object({ status: z.literal("requested") }),
156
- ...GithubAiLinterPublicationResult.options
157
- ]);
158
- const ReducedDiagnostic = z.object({
159
- classification: z.enum([
160
- "new",
161
- "persistent",
162
- "reintroduced"
163
- ]).nullable(),
164
- diagnostic: GithubAiLinterDiagnostic,
165
- eventOffset: StreamOffset,
166
- suppression: GithubAiLinterDiagnosticSuppressedPayload.nullable()
167
- });
168
- const AnalysisSummary = z.object({
169
- analysisRequestOffset: StreamOffset,
170
- baseSha: z.string().min(1),
171
- diagnosticCount: z.number().int().nonnegative(),
172
- headSha: z.string().min(1),
173
- publication: PublicationState,
174
- rulesCommit: z.string().min(1),
175
- status: z.enum([
176
- "running",
177
- "succeeded",
178
- "cancelled",
179
- "failed"
180
- ]),
181
- suppressedDiagnosticCount: z.number().int().nonnegative()
182
- });
183
- const MaterializedAnalysis = z.object({
184
- analysisRequestOffset: StreamOffset,
185
- assessment: GithubAiLinterAssessment,
186
- diagnostics: z.array(ReducedDiagnostic),
187
- request: GithubAiLinterAnalysisRequested,
188
- resolvedDiagnostics: z.array(GithubAiLinterDiagnostic)
189
- });
190
- const ActiveAnalysis = z.object({
191
- /**
192
- * There is deliberately no wall-clock expiry in the first slice. New pushes
193
- * cancel old work, while the Agent processor's autonomous-turn breaker
194
- * explicitly fails an analysis which cannot finish within its configured
195
- * budget. A future time limit should likewise be a typed processor-authored
196
- * settlement event driven by a durable alarm, not an implicit timestamp
197
- * check that silently changes reduced state.
198
- */
199
- analysisRequestOffset: StreamOffset,
200
- diagnostics: z.array(ReducedDiagnostic),
201
- request: GithubAiLinterAnalysisRequested
202
- });
203
- const GithubAiLinterProcessorContract = defineProcessorContract({
204
- slug: "github-ai-linter",
205
- version: "0.4.0",
206
- description: "Reduces one pull request's AI diagnostics and mechanically publishes its GitHub Check Run and optional advisory review.",
207
- stateSchema: z.object({
208
- /**
209
- * These are intentionally lightweight headers, not copies of every prompt
210
- * and diagnostic. The stream remains the canonical full history. If a PR
211
- * eventually accumulates enough pushes for even these headers to matter,
212
- * move cold headers to a paged read model rather than retaining full
213
- * diagnostics in Durable Object state.
214
- */
215
- analyses: z.array(AnalysisSummary).default([]),
216
- currentAnalysis: ActiveAnalysis.nullable().default(null),
217
- latestSuccessfulAnalysis: MaterializedAnalysis.nullable().default(null),
218
- /**
219
- * This small semantic-key index is what lets a later result distinguish
220
- * "new" from "reintroduced." A production-scale rule engine should replace
221
- * it with a compact/bounded index; the event history already contains the
222
- * authoritative data needed to rebuild one.
223
- */
224
- seenDiagnosticKeys: z.array(z.string()).default([])
225
- }),
226
- events: {
227
- [githubAiLinterEventTypes.analysisRequested]: {
228
- description: "Pins one pull-request head and immutable rules snapshot for analysis.",
229
- payloadSchema: GithubAiLinterAnalysisRequested
230
- },
231
- [githubAiLinterEventTypes.diagnosticReported]: {
232
- description: "One Oxlint-shaped diagnostic reported by the analysis agent.",
233
- payloadSchema: GithubAiLinterDiagnosticReportedPayload
234
- },
235
- [githubAiLinterEventTypes.diagnosticSuppressed]: {
236
- description: "Records that a source directive suppresses one reported diagnostic.",
237
- payloadSchema: GithubAiLinterDiagnosticSuppressedPayload
238
- },
239
- [githubAiLinterEventTypes.analysisSettled]: {
240
- description: "The sole terminal fact for an analysis request.",
241
- payloadSchema: GithubAiLinterAnalysisSettledPayload
242
- },
243
- [githubAiLinterEventTypes.reviewPublicationRequested]: {
244
- description: "Opens the durable obligation to publish one GitHub Check Run and, for findings, one immutable non-blocking review.",
245
- payloadSchema: z.object({ analysisRequestOffset: StreamOffset })
246
- },
247
- [githubAiLinterEventTypes.reviewPublicationSettled]: {
248
- description: "Records the terminal GitHub Check Run and review publication result.",
249
- payloadSchema: z.object({
250
- analysisRequestOffset: StreamOffset,
251
- result: GithubAiLinterPublicationResult
252
- })
253
- }
254
- },
255
- processorDeps: [{ "events.iterate.com/agent/paused": {
256
- description: "The generic Agent processor paused its autonomous turn loop.",
257
- payloadSchema: z.object({
258
- reason: z.string().optional(),
259
- triggerOffset: StreamOffset.optional()
260
- })
261
- } }],
262
- consumes: [...Object.values(githubAiLinterEventTypes), "events.iterate.com/agent/paused"],
263
- emits: [
264
- githubAiLinterEventTypes.analysisSettled,
265
- githubAiLinterEventTypes.reviewPublicationRequested,
266
- githubAiLinterEventTypes.reviewPublicationSettled
267
- ]
268
- });
269
- //#endregion
270
- //#region src/starter-apps/github-ai-linter/worker-ref.ts
271
- const configuredWorkerEntrypoint = "node_modules/iterate/dist/starter-apps/github-ai-linter/configured-worker.mjs";
272
- const REVIEW_BOT_SUBSCRIPTION_NAME = "review-bot";
273
- const REVIEW_BOT_RELEVANT_WEBHOOK_CONDITION = [
274
- "(payload.delivery.name = \"pull_request\" and",
275
- "(payload.body.action = \"opened\" or",
276
- "payload.body.action = \"ready_for_review\" or",
277
- "payload.body.action = \"synchronize\"))",
278
- "or",
279
- "((payload.delivery.name = \"issue_comment\" or",
280
- "payload.delivery.name = \"pull_request_review\" or",
281
- "payload.delivery.name = \"pull_request_review_comment\") and",
282
- "$count(payload.associations.mentionedUsers) > 0)"
283
- ].join(" ");
284
- /**
285
- * The review router only needs lifecycle deliveries and explicit mentions.
286
- * Filtering on the source stream keeps check/workflow webhook bursts out of
287
- * the hosted processor while the offset prefix preserves the restore cutoff.
288
- */
289
- function reviewBotSubscriptionCondition(startAfterOffset) {
290
- return `offset > ${startAfterOffset} and (${REVIEW_BOT_RELEVANT_WEBHOOK_CONDITION})`;
291
- }
292
- async function reviewBotSubscriptionEvent(sourceEvent, connection, config, startAfterOffset) {
293
- return {
294
- type: "events.iterate.com/stream/subscription-configured",
295
- payload: {
296
- name: REVIEW_BOT_SUBSCRIPTION_NAME,
297
- filter: {
298
- eventTypes: ["events.iterate.com/github/webhook-received"],
299
- jsonataCondition: reviewBotSubscriptionCondition(startAfterOffset)
300
- },
301
- receiver: {
302
- action: "wake-processor",
303
- expression: [
304
- "workers",
305
- ["get", await reviewBotAppRef(connection, config)],
306
- "processor",
307
- "wakeStreamProcessor"
308
- ]
309
- }
310
- },
311
- idempotencyKey: `review-bot/subscription:${sourceEvent.path}:${sourceEvent.offset}`
312
- };
313
- }
314
- async function pullRequestLinterSubscriptionEvent(input, config) {
315
- return {
316
- type: "events.iterate.com/stream/subscription-configured",
317
- payload: {
318
- name: "github-ai-linter",
319
- filter: { eventTypes: GithubAiLinterProcessorContract.consumes },
320
- receiver: {
321
- action: "wake-processor",
322
- expression: [
323
- "workers",
324
- ["get", await pullRequestLinterAppRef(input, config)],
325
- "processor",
326
- "wakeStreamProcessor"
327
- ]
328
- }
329
- },
330
- idempotencyKey: [
331
- "github-ai-linter/subscription",
332
- input.connection,
333
- input.repositoryId,
334
- input.pullRequestNumber,
335
- `policy:${config.policyVersion}`,
336
- "delivery:2",
337
- `stream:${input.streamPath}`
338
- ].join(":")
339
- };
340
- }
341
- async function reviewBotAppRef(connection, config) {
342
- return dynamicWorkerRef({
343
- className: "ReviewBotApp",
344
- config,
345
- durableWorkerKey: `github-ai-linter-review-bot-${await durableIdentity(connection)}`
346
- });
347
- }
348
- async function pullRequestLinterAppRef(input, config) {
349
- return dynamicWorkerRef({
350
- className: "GithubAiLinterApp",
351
- config,
352
- durableWorkerKey: `app-gh-linter-${await durableIdentity([
353
- input.connection,
354
- String(input.repositoryId),
355
- String(input.pullRequestNumber),
356
- input.streamPath
357
- ].join("\0"))}`
358
- });
359
- }
360
- function dynamicWorkerRef(input) {
361
- return {
362
- type: "stateful",
363
- path: "/",
364
- className: input.className,
365
- durableWorkerKey: input.durableWorkerKey,
366
- source: { createWorker: {
367
- entryPoint: configuredWorkerEntrypoint,
368
- files: {
369
- type: "repo",
370
- repoPath: "/repos/config",
371
- include: ["package.json"]
372
- },
373
- minify: true,
374
- virtualModules: { "iterate:github-ai-linter-config": `export default ${JSON.stringify(input.config)};` }
375
- } }
376
- };
377
- }
378
- /**
379
- * Dynamic-worker durable keys have a 63-character ceiling and connection
380
- * slugs are user-controlled. A truncated SHA-256 preserves stable identity
381
- * without leaking or squeezing arbitrary coordinates into that limit.
382
- */
383
- async function durableIdentity(value) {
384
- const digest = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(value));
385
- return [...new Uint8Array(digest).slice(0, 16)].map((byte) => byte.toString(16).padStart(2, "0")).join("");
386
- }
387
- //#endregion
388
- export { githubAiLinterEventTypes as a, GithubAiLinterProcessorContract as i, pullRequestLinterSubscriptionEvent as n, reviewBotSubscriptionEvent as r, REVIEW_BOT_SUBSCRIPTION_NAME as t };
389
-
390
- //# sourceMappingURL=worker-ref-DZxPDmb_.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"worker-ref-DZxPDmb_.mjs","names":[],"sources":["../src/starter-apps/github-ai-linter/contract.ts","../src/starter-apps/github-ai-linter/worker-ref.ts"],"sourcesContent":["import { z } from \"zod\";\nimport { defineProcessorContract } from \"../../processors/index.ts\";\n\n/**\n * Keep the vocabulary flat. These names are also copied into the linter\n * agent's developer task, so changing one here deliberately breaks an old\n * prompt instead of leaving two almost-compatible protocols alive.\n *\n * The const assertion preserves exact event literals for contract typing. It\n * is safe because this object is static vocabulary and is never mutated.\n */\nexport const githubAiLinterEventTypes = {\n analysisRequested: \"events.iterate.com/github-ai-linter/analysis-requested\",\n diagnosticReported: \"events.iterate.com/github-ai-linter/diagnostic-reported\",\n diagnosticSuppressed: \"events.iterate.com/github-ai-linter/diagnostic-suppressed\",\n analysisSettled: \"events.iterate.com/github-ai-linter/analysis-settled\",\n reviewPublicationRequested: \"events.iterate.com/github-ai-linter/review-publication-requested\",\n reviewPublicationSettled: \"events.iterate.com/github-ai-linter/review-publication-settled\",\n} as const;\n\nconst PositiveSafeInteger = z.number().int().positive().max(Number.MAX_SAFE_INTEGER);\n// Stream offset zero is the valid \"before the first event\" coordinate in the\n// processor APIs. Keeping it distinct from GitHub IDs and source lines avoids\n// accidentally rejecting a request simply because it was the stream's first\n// committed event.\nconst StreamOffset = z.number().int().nonnegative().max(Number.MAX_SAFE_INTEGER);\nconst RuleName = z.string().regex(/^[a-z0-9-]+(?:\\/[a-z0-9-]+)*$/);\n\nconst GithubAiLinterRule = z.object({\n files: z.array(z.string().min(1)).min(1),\n invariant: z.string().min(1),\n severity: z.enum([\"error\", \"warning\"]),\n suggestions: z.enum([\"allowed\", \"forbidden\"]).default(\"allowed\"),\n});\n\nexport const GithubAiLinterAnalysisRequested = z.object({\n appSlug: z.string().min(1),\n baseSha: z.string().min(1),\n connection: z.string().min(1),\n headSha: z.string().min(1),\n policyVersion: z.string().min(1),\n promptVersion: z.string().min(1),\n pullRequestNumber: PositiveSafeInteger,\n repository: z.object({\n id: PositiveSafeInteger,\n owner: z.string().min(1),\n repo: z.string().min(1),\n }),\n rules: z.record(RuleName, GithubAiLinterRule),\n rulesCommit: z.string().min(1),\n});\n\nconst SourceSpanSchema = z\n .object({\n endColumn: PositiveSafeInteger.optional(),\n endLine: PositiveSafeInteger,\n startColumn: PositiveSafeInteger.optional(),\n startLine: PositiveSafeInteger,\n })\n .refine(\n ({ endLine, startLine }) => endLine >= startLine,\n \"a source span must end on or after its start line\",\n );\nconst WholeLineSpanSchema = z\n .object({\n endLine: PositiveSafeInteger,\n startLine: PositiveSafeInteger,\n })\n .refine(\n ({ endLine, startLine }) => endLine >= startLine,\n \"a source span must end on or after its start line\",\n );\n\nconst GithubAiLinterDiagnostic = z.object({\n /**\n * Cross-analysis identity. Unlike the GitHub line, this should survive\n * nearby edits: rule + filename + a short semantic anchor is the intended\n * input. The prompt explicitly forbids line numbers and prose here.\n */\n diagnosticKey: z.string().min(1).max(500),\n filename: z.string().min(1).max(2_000),\n fix: z\n .object({\n content: z.string().max(50_000),\n /**\n * The first slice only publishes human-applied GitHub suggestions.\n * A future `fix` kind may authorize an automated branch update, but it\n * must be a separate explicit protocol: never reinterpret an archived\n * suggestion as permission to mutate code.\n */\n kind: z.literal(\"suggestion\"),\n span: WholeLineSpanSchema,\n })\n .optional(),\n help: z.string().min(1).max(8_000).optional(),\n /**\n * Oxlint diagnostics can carry several labels. The first label is the\n * primary one and supplies GitHub's inline location in this first version;\n * later labels remain structured context for a richer renderer.\n */\n labels: z\n .array(\n z.object({\n message: z.string().min(1).max(4_000).optional(),\n span: SourceSpanSchema,\n }),\n )\n .min(1)\n .max(20),\n message: z.string().min(1).max(8_000),\n ruleName: RuleName,\n severity: z.enum([\"error\", \"warning\"]),\n});\n\nconst GithubAiLinterDiagnosticReportedPayload = GithubAiLinterDiagnostic.extend({\n analysisRequestOffset: StreamOffset,\n});\n\nconst GithubAiLinterDiagnosticSuppressedPayload = z.object({\n analysisRequestOffset: StreamOffset,\n diagnosticOffset: StreamOffset,\n directive: z.enum([\"disable\", \"disable-line\", \"disable-next-line\"]),\n filename: z.string().min(1).max(2_000),\n line: PositiveSafeInteger,\n reason: z.string().min(1).max(4_000),\n});\n\nconst GithubAiLinterAssessment = z.object({\n summary: z.string().min(1).max(20_000),\n verdict: z.enum([\"approve\", \"comment\", \"request-changes\"]),\n});\n\nconst GithubAiLinterAnalysisResult = z.discriminatedUnion(\"status\", [\n z.object({\n assessment: GithubAiLinterAssessment,\n status: z.literal(\"succeeded\"),\n }),\n z.object({\n reason: z.string().min(1).max(8_000),\n status: z.literal(\"cancelled\"),\n }),\n z.object({\n error: z.string().min(1).max(8_000),\n status: z.literal(\"failed\"),\n }),\n]);\n\nconst GithubAiLinterAnalysisSettledPayload = z.object({\n analysisRequestOffset: StreamOffset,\n result: GithubAiLinterAnalysisResult,\n});\n\nconst PublishedCheckRun = z.object({\n id: PositiveSafeInteger,\n url: z.string().url(),\n});\n\nexport const GithubAiLinterPublicationResult = z.discriminatedUnion(\"status\", [\n z.object({\n checkRun: PublishedCheckRun,\n reason: z.string().min(1).max(8_000),\n status: z.literal(\"skipped\"),\n }),\n z.object({\n // Optional only for replay compatibility with successful publication\n // events written before the linter began publishing Check Runs.\n checkRun: PublishedCheckRun.optional(),\n reviewId: PositiveSafeInteger,\n reviewUrl: z.string().url(),\n status: z.literal(\"succeeded\"),\n }),\n z.object({\n reason: z.string().min(1).max(8_000),\n status: z.literal(\"cancelled\"),\n }),\n z.object({\n error: z.string().min(1).max(8_000),\n status: z.literal(\"failed\"),\n }),\n]);\n\nconst PublicationState = z.discriminatedUnion(\"status\", [\n z.object({ status: z.literal(\"not-requested\") }),\n z.object({ status: z.literal(\"requested\") }),\n ...GithubAiLinterPublicationResult.options,\n]);\n\nconst ReducedDiagnostic = z.object({\n classification: z.enum([\"new\", \"persistent\", \"reintroduced\"]).nullable(),\n diagnostic: GithubAiLinterDiagnostic,\n eventOffset: StreamOffset,\n suppression: GithubAiLinterDiagnosticSuppressedPayload.nullable(),\n});\n\nconst AnalysisSummary = z.object({\n analysisRequestOffset: StreamOffset,\n baseSha: z.string().min(1),\n diagnosticCount: z.number().int().nonnegative(),\n headSha: z.string().min(1),\n publication: PublicationState,\n rulesCommit: z.string().min(1),\n status: z.enum([\"running\", \"succeeded\", \"cancelled\", \"failed\"]),\n suppressedDiagnosticCount: z.number().int().nonnegative(),\n});\n\nconst MaterializedAnalysis = z.object({\n analysisRequestOffset: StreamOffset,\n assessment: GithubAiLinterAssessment,\n diagnostics: z.array(ReducedDiagnostic),\n request: GithubAiLinterAnalysisRequested,\n resolvedDiagnostics: z.array(GithubAiLinterDiagnostic),\n});\n\nconst ActiveAnalysis = z.object({\n /**\n * There is deliberately no wall-clock expiry in the first slice. New pushes\n * cancel old work, while the Agent processor's autonomous-turn breaker\n * explicitly fails an analysis which cannot finish within its configured\n * budget. A future time limit should likewise be a typed processor-authored\n * settlement event driven by a durable alarm, not an implicit timestamp\n * check that silently changes reduced state.\n */\n analysisRequestOffset: StreamOffset,\n diagnostics: z.array(ReducedDiagnostic),\n request: GithubAiLinterAnalysisRequested,\n});\n\nexport const GithubAiLinterState = z.object({\n /**\n * These are intentionally lightweight headers, not copies of every prompt\n * and diagnostic. The stream remains the canonical full history. If a PR\n * eventually accumulates enough pushes for even these headers to matter,\n * move cold headers to a paged read model rather than retaining full\n * diagnostics in Durable Object state.\n */\n analyses: z.array(AnalysisSummary).default([]),\n currentAnalysis: ActiveAnalysis.nullable().default(null),\n latestSuccessfulAnalysis: MaterializedAnalysis.nullable().default(null),\n /**\n * This small semantic-key index is what lets a later result distinguish\n * \"new\" from \"reintroduced.\" A production-scale rule engine should replace\n * it with a compact/bounded index; the event history already contains the\n * authoritative data needed to rebuild one.\n */\n seenDiagnosticKeys: z.array(z.string()).default([]),\n});\n\nexport const GithubAiLinterProcessorContract = defineProcessorContract({\n slug: \"github-ai-linter\",\n version: \"0.4.0\",\n description:\n \"Reduces one pull request's AI diagnostics and mechanically publishes its GitHub Check Run and optional advisory review.\",\n stateSchema: GithubAiLinterState,\n events: {\n [githubAiLinterEventTypes.analysisRequested]: {\n description: \"Pins one pull-request head and immutable rules snapshot for analysis.\",\n payloadSchema: GithubAiLinterAnalysisRequested,\n },\n [githubAiLinterEventTypes.diagnosticReported]: {\n description: \"One Oxlint-shaped diagnostic reported by the analysis agent.\",\n payloadSchema: GithubAiLinterDiagnosticReportedPayload,\n },\n [githubAiLinterEventTypes.diagnosticSuppressed]: {\n description: \"Records that a source directive suppresses one reported diagnostic.\",\n payloadSchema: GithubAiLinterDiagnosticSuppressedPayload,\n },\n [githubAiLinterEventTypes.analysisSettled]: {\n description: \"The sole terminal fact for an analysis request.\",\n payloadSchema: GithubAiLinterAnalysisSettledPayload,\n },\n [githubAiLinterEventTypes.reviewPublicationRequested]: {\n description:\n \"Opens the durable obligation to publish one GitHub Check Run and, for findings, one immutable non-blocking review.\",\n payloadSchema: z.object({ analysisRequestOffset: StreamOffset }),\n },\n [githubAiLinterEventTypes.reviewPublicationSettled]: {\n description: \"Records the terminal GitHub Check Run and review publication result.\",\n payloadSchema: z.object({\n analysisRequestOffset: StreamOffset,\n result: GithubAiLinterPublicationResult,\n }),\n },\n },\n // `agent/paused` is owned by the platform Agent contract. This userspace\n // processor consumes it only to turn an exhausted analysis into a durable\n // terminal fact instead of leaving it visibly `running`.\n processorDeps: [\n {\n \"events.iterate.com/agent/paused\": {\n description: \"The generic Agent processor paused its autonomous turn loop.\",\n payloadSchema: z.object({\n reason: z.string().optional(),\n triggerOffset: StreamOffset.optional(),\n }),\n },\n },\n ],\n consumes: [...Object.values(githubAiLinterEventTypes), \"events.iterate.com/agent/paused\"],\n // `diagnostic-reported` and `diagnostic-suppressed` are declared above and\n // consumed here, but are not processor emissions: the generic Agent appends\n // them with its ordinary stream capability. This list is deliberately only\n // the mechanical processor's own consequences.\n emits: [\n githubAiLinterEventTypes.analysisSettled,\n githubAiLinterEventTypes.reviewPublicationRequested,\n githubAiLinterEventTypes.reviewPublicationSettled,\n ],\n});\n\nexport type GithubAiLinterProcessorContract = typeof GithubAiLinterProcessorContract;\nexport type GithubAiLinterState = z.infer<typeof GithubAiLinterState>;\nexport type GithubAiLinterAnalysisRequested = z.infer<typeof GithubAiLinterAnalysisRequested>;\nexport type GithubAiLinterPublicationResult = z.infer<typeof GithubAiLinterPublicationResult>;\n","import type { StatefulDynamicWorkerRef, StreamEvent, StreamEventInput } from \"../../sdk.ts\";\nimport { GithubAiLinterProcessorContract } from \"./contract.ts\";\nimport type { GithubAiLinterRuleSource } from \"./rules.ts\";\n\nexport type GithubAiLinterConfig = {\n /**\n * Operators bump this when rule selection or policy meaning changes. It is\n * part of analysis identity, so an unchanged pull-request head is analysed\n * again instead of colliding with an older task.\n */\n policyVersion: string;\n rules: GithubAiLinterRuleSource;\n};\n\nconst configuredWorkerEntrypoint =\n \"node_modules/iterate/dist/starter-apps/github-ai-linter/configured-worker.mjs\";\n\n// Subscription names are opaque, source-local identities under the\n// subscription-model redesign — the old `app-…#slug` placement-encoding\n// convention is dead. Plain contract-slug names read as\n// `subscriptions.get(\"review-bot\")`.\nexport const REVIEW_BOT_SUBSCRIPTION_NAME = \"review-bot\";\n\nconst REVIEW_BOT_RELEVANT_WEBHOOK_CONDITION = [\n '(payload.delivery.name = \"pull_request\" and',\n '(payload.body.action = \"opened\" or',\n 'payload.body.action = \"ready_for_review\" or',\n 'payload.body.action = \"synchronize\"))',\n \"or\",\n '((payload.delivery.name = \"issue_comment\" or',\n 'payload.delivery.name = \"pull_request_review\" or',\n 'payload.delivery.name = \"pull_request_review_comment\") and',\n \"$count(payload.associations.mentionedUsers) > 0)\",\n].join(\" \");\n\n/**\n * The review router only needs lifecycle deliveries and explicit mentions.\n * Filtering on the source stream keeps check/workflow webhook bursts out of\n * the hosted processor while the offset prefix preserves the restore cutoff.\n */\nfunction reviewBotSubscriptionCondition(startAfterOffset: number) {\n return `offset > ${startAfterOffset} and (${REVIEW_BOT_RELEVANT_WEBHOOK_CONDITION})`;\n}\n\nexport async function reviewBotSubscriptionEvent(\n sourceEvent: StreamEvent,\n connection: string,\n config: GithubAiLinterConfig,\n startAfterOffset: number,\n): Promise<StreamEventInput> {\n return {\n type: \"events.iterate.com/stream/subscription-configured\",\n payload: {\n name: REVIEW_BOT_SUBSCRIPTION_NAME,\n // A restored connection stream can contain thousands of old webhooks.\n // This cutoff gives a newly configured review bot future work only.\n // Config refreshes preserve the original cutoff in index.ts.\n filter: {\n eventTypes: [\"events.iterate.com/github/webhook-received\"],\n jsonataCondition: reviewBotSubscriptionCondition(startAfterOffset),\n },\n receiver: {\n action: \"wake-processor\",\n expression: [\n \"workers\",\n [\"get\", await reviewBotAppRef(connection, config)],\n \"processor\",\n \"wakeStreamProcessor\",\n ],\n },\n },\n idempotencyKey: `review-bot/subscription:${sourceEvent.path}:${sourceEvent.offset}`,\n };\n}\n\nexport async function pullRequestLinterSubscriptionEvent(\n input: {\n connection: string;\n pullRequestNumber: number;\n repositoryId: number;\n // A processor host permanently adopts its first stream coordinate. The\n // path keeps two project-controlled repo aliases for the same GitHub PR\n // from accidentally dialing the same Durable Object.\n streamPath: string;\n },\n config: GithubAiLinterConfig,\n): Promise<StreamEventInput> {\n return {\n type: \"events.iterate.com/stream/subscription-configured\",\n payload: {\n name: \"github-ai-linter\",\n // The processor contract is the one vocabulary authority. In particular,\n // it includes `agent/paused`, which turns an exhausted review into its\n // durable terminal analysis settlement.\n filter: {\n eventTypes: GithubAiLinterProcessorContract.consumes,\n },\n receiver: {\n action: \"wake-processor\",\n expression: [\n \"workers\",\n [\"get\", await pullRequestLinterAppRef(input, config)],\n \"processor\",\n \"wakeStreamProcessor\",\n ],\n },\n },\n // Every route coordinate which changes the worker ref is part of the key.\n // Policy changes and delivery-shape changes have independent revisions:\n // the latter prevents a persisted old filter from colliding with its\n // replacement under same-key/different-body validation. `delivery:2` is\n // the durable filter/receiver shape; bump it when either changes.\n idempotencyKey: [\n \"github-ai-linter/subscription\",\n input.connection,\n input.repositoryId,\n input.pullRequestNumber,\n `policy:${config.policyVersion}`,\n \"delivery:2\",\n `stream:${input.streamPath}`,\n ].join(\":\"),\n };\n}\n\nasync function reviewBotAppRef(\n connection: string,\n config: GithubAiLinterConfig,\n): Promise<StatefulDynamicWorkerRef> {\n return dynamicWorkerRef({\n className: \"ReviewBotApp\",\n config,\n durableWorkerKey: `github-ai-linter-review-bot-${await durableIdentity(connection)}`,\n });\n}\n\nasync function pullRequestLinterAppRef(\n input: {\n connection: string;\n pullRequestNumber: number;\n repositoryId: number;\n streamPath: string;\n },\n config: GithubAiLinterConfig,\n): Promise<StatefulDynamicWorkerRef> {\n const identity = [\n input.connection,\n String(input.repositoryId),\n String(input.pullRequestNumber),\n input.streamPath,\n ].join(\"\\0\");\n return dynamicWorkerRef({\n className: \"GithubAiLinterApp\",\n config,\n durableWorkerKey: `app-gh-linter-${await durableIdentity(identity)}`,\n });\n}\n\nfunction dynamicWorkerRef(input: {\n className: string;\n config: GithubAiLinterConfig;\n durableWorkerKey: string;\n}): StatefulDynamicWorkerRef {\n return {\n type: \"stateful\",\n path: \"/\",\n className: input.className,\n durableWorkerKey: input.durableWorkerKey,\n source: {\n createWorker: {\n entryPoint: configuredWorkerEntrypoint,\n files: {\n type: \"repo\",\n repoPath: \"/repos/config\",\n include: [\"package.json\"],\n },\n minify: true,\n virtualModules: {\n \"iterate:github-ai-linter-config\": `export default ${JSON.stringify(input.config)};`,\n },\n },\n },\n };\n}\n\n/**\n * Dynamic-worker durable keys have a 63-character ceiling and connection\n * slugs are user-controlled. A truncated SHA-256 preserves stable identity\n * without leaking or squeezing arbitrary coordinates into that limit.\n */\nasync function durableIdentity(value: string) {\n const digest = await crypto.subtle.digest(\"SHA-256\", new TextEncoder().encode(value));\n return [...new Uint8Array(digest).slice(0, 16)]\n .map((byte) => byte.toString(16).padStart(2, \"0\"))\n .join(\"\");\n}\n"],"mappings":"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"}
package/dist/worker.d.mts DELETED
@@ -1,33 +0,0 @@
1
- import { WorkerEntrypoint } from "cloudflare:workers";
2
-
3
- export type IterateStreamAppendInput = {
4
- event: unknown;
5
- streamPath?: string;
6
- };
7
-
8
- export type IterateProjectStreams = {
9
- append(input: IterateStreamAppendInput): Promise<unknown>;
10
- };
11
-
12
- export type IterateProjectItx<Context = unknown> = {
13
- context: Promise<Context>;
14
- };
15
-
16
- export type IterateProjectEnv<Context = unknown> = {
17
- ITERATE: IterateProjectItx<Context>;
18
- STREAMS: IterateProjectStreams;
19
- };
20
-
21
- export type IterateProjectEventInput = {
22
- event: unknown;
23
- streamPath: string;
24
- };
25
-
26
- export declare class IterateProjectEntrypoint<Context = unknown> extends WorkerEntrypoint<
27
- IterateProjectEnv<Context>
28
- > {
29
- get itx(): IterateProjectItx<Context>;
30
- get streams(): IterateProjectStreams;
31
- processEvent(input: IterateProjectEventInput): Promise<void>;
32
- protected onProjectEvent(input: IterateProjectEventInput): Promise<void>;
33
- }
package/dist/worker.mjs DELETED
@@ -1,18 +0,0 @@
1
- import { WorkerEntrypoint } from "cloudflare:workers";
2
- //#region src/worker.ts
3
- var IterateProjectEntrypoint = class extends WorkerEntrypoint {
4
- get itx() {
5
- return this.env.ITERATE;
6
- }
7
- get streams() {
8
- return this.env.STREAMS;
9
- }
10
- async processEvent(input) {
11
- await this.onProjectEvent(input);
12
- }
13
- async onProjectEvent(_input) {}
14
- };
15
- //#endregion
16
- export { IterateProjectEntrypoint };
17
-
18
- //# sourceMappingURL=worker.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"worker.mjs","names":[],"sources":["../src/worker.ts"],"sourcesContent":["import { WorkerEntrypoint } from \"cloudflare:workers\";\n\nexport type IterateStreamAppendInput = {\n event: unknown;\n streamPath?: string;\n};\n\nexport type IterateProjectStreams = {\n append: (input: IterateStreamAppendInput) => Promise<unknown>;\n};\n\nexport type IterateProjectItx<Context = unknown> = {\n context: Promise<Context>;\n};\n\nexport type IterateProjectEnv<Context = unknown> = {\n ITERATE: IterateProjectItx<Context>;\n STREAMS: IterateProjectStreams;\n};\n\nexport type IterateProjectEventInput = {\n event: unknown;\n streamPath: string;\n};\n\nexport class IterateProjectEntrypoint<Context = unknown> extends WorkerEntrypoint<\n IterateProjectEnv<Context>\n> {\n get itx(): IterateProjectItx<Context> {\n return this.env.ITERATE;\n }\n\n get streams(): IterateProjectEnv[\"STREAMS\"] {\n return this.env.STREAMS;\n }\n\n async processEvent(input: IterateProjectEventInput): Promise<void> {\n await this.onProjectEvent(input);\n }\n\n protected async onProjectEvent(_input: IterateProjectEventInput): Promise<void> {}\n}\n"],"mappings":";;AAyBA,IAAa,2BAAb,cAAiE,iBAE/D;CACA,IAAI,MAAkC;EACpC,OAAO,KAAK,IAAI;CAClB;CAEA,IAAI,UAAwC;EAC1C,OAAO,KAAK,IAAI;CAClB;CAEA,MAAM,aAAa,OAAgD;EACjE,MAAM,KAAK,eAAe,KAAK;CACjC;CAEA,MAAgB,eAAe,QAAiD,CAAC;AACnF"}
@@ -1,12 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
- <!--
4
- Used only when building with a real SIGN_IDENTITY (see build-menubar-app.sh).
5
- Local UserNotifications need no special entitlement — this is the hardened-
6
- runtime baseline, and the place to add keys (e.g. aps-environment for remote
7
- push, or app-sandbox) if this ever ships through the App Store / notarization.
8
- -->
9
- <plist version="1.0">
10
- <dict>
11
- </dict>
12
- </plist>