@llm4ts/flow 0.1.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 (198) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +41 -0
  3. package/dist/AzureDevOpsTool.d.ts +60 -0
  4. package/dist/AzureDevOpsTool.d.ts.map +1 -0
  5. package/dist/AzureDevOpsTool.js +163 -0
  6. package/dist/AzureDevOpsTool.js.map +1 -0
  7. package/dist/Bench.d.ts +133 -0
  8. package/dist/Bench.d.ts.map +1 -0
  9. package/dist/Bench.js +272 -0
  10. package/dist/Bench.js.map +1 -0
  11. package/dist/BenchReport.d.ts +9 -0
  12. package/dist/BenchReport.d.ts.map +1 -0
  13. package/dist/BenchReport.js +360 -0
  14. package/dist/BenchReport.js.map +1 -0
  15. package/dist/CapabilityGuard.d.ts +6 -0
  16. package/dist/CapabilityGuard.d.ts.map +1 -0
  17. package/dist/CapabilityGuard.js +25 -0
  18. package/dist/CapabilityGuard.js.map +1 -0
  19. package/dist/Chat.d.ts +15 -0
  20. package/dist/Chat.d.ts.map +1 -0
  21. package/dist/Chat.js +36 -0
  22. package/dist/Chat.js.map +1 -0
  23. package/dist/Classified.d.ts +14 -0
  24. package/dist/Classified.d.ts.map +1 -0
  25. package/dist/Classified.js +48 -0
  26. package/dist/Classified.js.map +1 -0
  27. package/dist/CostLedger.d.ts +55 -0
  28. package/dist/CostLedger.d.ts.map +1 -0
  29. package/dist/CostLedger.js +126 -0
  30. package/dist/CostLedger.js.map +1 -0
  31. package/dist/CostTracker.d.ts +13 -0
  32. package/dist/CostTracker.d.ts.map +1 -0
  33. package/dist/CostTracker.js +116 -0
  34. package/dist/CostTracker.js.map +1 -0
  35. package/dist/Equiv.d.ts +163 -0
  36. package/dist/Equiv.d.ts.map +1 -0
  37. package/dist/Equiv.js +256 -0
  38. package/dist/Equiv.js.map +1 -0
  39. package/dist/EquivReport.d.ts +16 -0
  40. package/dist/EquivReport.d.ts.map +1 -0
  41. package/dist/EquivReport.js +77 -0
  42. package/dist/EquivReport.js.map +1 -0
  43. package/dist/Flow.d.ts +25 -0
  44. package/dist/Flow.d.ts.map +1 -0
  45. package/dist/Flow.js +39 -0
  46. package/dist/Flow.js.map +1 -0
  47. package/dist/FlowContext.d.ts +23 -0
  48. package/dist/FlowContext.d.ts.map +1 -0
  49. package/dist/FlowContext.js +4 -0
  50. package/dist/FlowContext.js.map +1 -0
  51. package/dist/FlowError.d.ts +80 -0
  52. package/dist/FlowError.d.ts.map +1 -0
  53. package/dist/FlowError.js +92 -0
  54. package/dist/FlowError.js.map +1 -0
  55. package/dist/FlowEvents.d.ts +101 -0
  56. package/dist/FlowEvents.d.ts.map +1 -0
  57. package/dist/FlowEvents.js +103 -0
  58. package/dist/FlowEvents.js.map +1 -0
  59. package/dist/FlowRecorder.d.ts +26 -0
  60. package/dist/FlowRecorder.d.ts.map +1 -0
  61. package/dist/FlowRecorder.js +74 -0
  62. package/dist/FlowRecorder.js.map +1 -0
  63. package/dist/GitHubTool.d.ts +53 -0
  64. package/dist/GitHubTool.d.ts.map +1 -0
  65. package/dist/GitHubTool.js +191 -0
  66. package/dist/GitHubTool.js.map +1 -0
  67. package/dist/GitTool.d.ts +46 -0
  68. package/dist/GitTool.d.ts.map +1 -0
  69. package/dist/GitTool.js +97 -0
  70. package/dist/GitTool.js.map +1 -0
  71. package/dist/Interaction.d.ts +21 -0
  72. package/dist/Interaction.d.ts.map +1 -0
  73. package/dist/Interaction.js +9 -0
  74. package/dist/Interaction.js.map +1 -0
  75. package/dist/McpServer.d.ts +18 -0
  76. package/dist/McpServer.d.ts.map +1 -0
  77. package/dist/McpServer.js +122 -0
  78. package/dist/McpServer.js.map +1 -0
  79. package/dist/Mermaid.d.ts +7 -0
  80. package/dist/Mermaid.d.ts.map +1 -0
  81. package/dist/Mermaid.js +98 -0
  82. package/dist/Mermaid.js.map +1 -0
  83. package/dist/Pack.d.ts +40 -0
  84. package/dist/Pack.d.ts.map +1 -0
  85. package/dist/Pack.js +141 -0
  86. package/dist/Pack.js.map +1 -0
  87. package/dist/Package.d.ts +2 -0
  88. package/dist/Package.d.ts.map +1 -0
  89. package/dist/Package.js +2 -0
  90. package/dist/Package.js.map +1 -0
  91. package/dist/Persistence.d.ts +32 -0
  92. package/dist/Persistence.d.ts.map +1 -0
  93. package/dist/Persistence.js +85 -0
  94. package/dist/Persistence.js.map +1 -0
  95. package/dist/Plan.d.ts +26 -0
  96. package/dist/Plan.d.ts.map +1 -0
  97. package/dist/Plan.js +101 -0
  98. package/dist/Plan.js.map +1 -0
  99. package/dist/PlanExecution.d.ts +7 -0
  100. package/dist/PlanExecution.d.ts.map +1 -0
  101. package/dist/PlanExecution.js +19 -0
  102. package/dist/PlanExecution.js.map +1 -0
  103. package/dist/Planner.d.ts +32 -0
  104. package/dist/Planner.d.ts.map +1 -0
  105. package/dist/Planner.js +97 -0
  106. package/dist/Planner.js.map +1 -0
  107. package/dist/PrSummary.d.ts +15 -0
  108. package/dist/PrSummary.d.ts.map +1 -0
  109. package/dist/PrSummary.js +29 -0
  110. package/dist/PrSummary.js.map +1 -0
  111. package/dist/PriceList.d.ts +11 -0
  112. package/dist/PriceList.d.ts.map +1 -0
  113. package/dist/PriceList.js +79 -0
  114. package/dist/PriceList.js.map +1 -0
  115. package/dist/Provenance.d.ts +27 -0
  116. package/dist/Provenance.d.ts.map +1 -0
  117. package/dist/Provenance.js +38 -0
  118. package/dist/Provenance.js.map +1 -0
  119. package/dist/Replay.d.ts +29 -0
  120. package/dist/Replay.d.ts.map +1 -0
  121. package/dist/Replay.js +181 -0
  122. package/dist/Replay.js.map +1 -0
  123. package/dist/Review.d.ts +71 -0
  124. package/dist/Review.d.ts.map +1 -0
  125. package/dist/Review.js +204 -0
  126. package/dist/Review.js.map +1 -0
  127. package/dist/ReviewCache.d.ts +6 -0
  128. package/dist/ReviewCache.d.ts.map +1 -0
  129. package/dist/ReviewCache.js +28 -0
  130. package/dist/ReviewCache.js.map +1 -0
  131. package/dist/Reviewer.d.ts +12 -0
  132. package/dist/Reviewer.d.ts.map +1 -0
  133. package/dist/Reviewer.js +30 -0
  134. package/dist/Reviewer.js.map +1 -0
  135. package/dist/SpecChecks.d.ts +17 -0
  136. package/dist/SpecChecks.d.ts.map +1 -0
  137. package/dist/SpecChecks.js +107 -0
  138. package/dist/SpecChecks.js.map +1 -0
  139. package/dist/Survey.d.ts +32 -0
  140. package/dist/Survey.d.ts.map +1 -0
  141. package/dist/Survey.js +119 -0
  142. package/dist/Survey.js.map +1 -0
  143. package/dist/TransientRetry.d.ts +16 -0
  144. package/dist/TransientRetry.d.ts.map +1 -0
  145. package/dist/TransientRetry.js +102 -0
  146. package/dist/TransientRetry.js.map +1 -0
  147. package/dist/Workspace.d.ts +39 -0
  148. package/dist/Workspace.d.ts.map +1 -0
  149. package/dist/Workspace.js +192 -0
  150. package/dist/Workspace.js.map +1 -0
  151. package/dist/WorkspaceLayout.d.ts +3 -0
  152. package/dist/WorkspaceLayout.d.ts.map +1 -0
  153. package/dist/WorkspaceLayout.js +19 -0
  154. package/dist/WorkspaceLayout.js.map +1 -0
  155. package/dist/WorkspaceTools.d.ts +4 -0
  156. package/dist/WorkspaceTools.d.ts.map +1 -0
  157. package/dist/WorkspaceTools.js +130 -0
  158. package/dist/WorkspaceTools.js.map +1 -0
  159. package/package.json +91 -0
  160. package/src/AzureDevOpsTool.ts +291 -0
  161. package/src/Bench.ts +340 -0
  162. package/src/BenchReport.ts +447 -0
  163. package/src/CapabilityGuard.ts +43 -0
  164. package/src/Chat.ts +60 -0
  165. package/src/Classified.ts +67 -0
  166. package/src/CostLedger.ts +171 -0
  167. package/src/CostTracker.ts +170 -0
  168. package/src/Equiv.ts +378 -0
  169. package/src/EquivReport.ts +92 -0
  170. package/src/Flow.ts +72 -0
  171. package/src/FlowContext.ts +23 -0
  172. package/src/FlowError.ts +112 -0
  173. package/src/FlowEvents.ts +147 -0
  174. package/src/FlowRecorder.ts +116 -0
  175. package/src/GitHubTool.ts +315 -0
  176. package/src/GitTool.ts +214 -0
  177. package/src/Interaction.ts +23 -0
  178. package/src/McpServer.ts +168 -0
  179. package/src/Mermaid.ts +112 -0
  180. package/src/Pack.ts +213 -0
  181. package/src/Package.ts +1 -0
  182. package/src/Persistence.ts +198 -0
  183. package/src/Plan.ts +119 -0
  184. package/src/PlanExecution.ts +46 -0
  185. package/src/Planner.ts +134 -0
  186. package/src/PrSummary.ts +37 -0
  187. package/src/PriceList.ts +91 -0
  188. package/src/Provenance.ts +85 -0
  189. package/src/Replay.ts +265 -0
  190. package/src/Review.ts +337 -0
  191. package/src/ReviewCache.ts +45 -0
  192. package/src/Reviewer.ts +31 -0
  193. package/src/SpecChecks.ts +143 -0
  194. package/src/Survey.ts +144 -0
  195. package/src/TransientRetry.ts +238 -0
  196. package/src/Workspace.ts +255 -0
  197. package/src/WorkspaceLayout.ts +22 -0
  198. package/src/WorkspaceTools.ts +188 -0
@@ -0,0 +1,130 @@
1
+ import * as Effect from "effect/Effect";
2
+ import { ToolExecutionFailed, makeTool } from "@llm4ts/core/tools/Tool";
3
+ import { isJsonRecord } from "@llm4ts/core/providers/CliSupport";
4
+ const parameter = (parameters, name) => {
5
+ if (!isJsonRecord(parameters)) {
6
+ return Effect.fail(ToolExecutionFailed.make({
7
+ message: "tool parameters must be an object"
8
+ }));
9
+ }
10
+ const value = parameters[name];
11
+ return typeof value === "string"
12
+ ? Effect.succeed(value)
13
+ : Effect.fail(ToolExecutionFailed.make({
14
+ message: `parameter '${name}' must be a string`
15
+ }));
16
+ };
17
+ const optionalParameter = (parameters, name) => {
18
+ if (!isJsonRecord(parameters)) {
19
+ return Effect.fail(ToolExecutionFailed.make({
20
+ message: "tool parameters must be an object"
21
+ }));
22
+ }
23
+ const value = parameters[name];
24
+ return value === undefined || typeof value === "string"
25
+ ? Effect.succeed(value)
26
+ : Effect.fail(ToolExecutionFailed.make({
27
+ message: `parameter '${name}' must be a string when supplied`
28
+ }));
29
+ };
30
+ const mapWorkspaceError = Effect.mapError((error) => ToolExecutionFailed.make({ message: error.message }));
31
+ const pathSchema = {
32
+ type: "object",
33
+ properties: {
34
+ path: { type: "string" }
35
+ },
36
+ required: ["path"],
37
+ additionalProperties: false
38
+ };
39
+ const contentSchema = {
40
+ type: "object",
41
+ properties: {
42
+ path: { type: "string" },
43
+ contents: { type: "string" }
44
+ },
45
+ required: ["path", "contents"],
46
+ additionalProperties: false
47
+ };
48
+ export const workspaceTools = (workspace) => [
49
+ makeTool({
50
+ name: "workspace_read",
51
+ description: "Read a bounded UTF-8 file under the workspace root",
52
+ parameters: pathSchema,
53
+ tags: ["file", "read", "workspace"],
54
+ sandbox: "WorkspaceReadOnly",
55
+ execute: (parameters) => Effect.all({
56
+ path: parameter(parameters, "path")
57
+ }).pipe(Effect.flatMap(({ path }) => workspace.read(path)), mapWorkspaceError)
58
+ }),
59
+ makeTool({
60
+ name: "workspace_write",
61
+ description: "Write bounded UTF-8 content under the workspace root",
62
+ parameters: contentSchema,
63
+ tags: ["file", "write", "workspace"],
64
+ execute: (parameters) => Effect.all({
65
+ path: parameter(parameters, "path"),
66
+ contents: parameter(parameters, "contents")
67
+ }).pipe(Effect.flatMap(({ path, contents }) => workspace.write(path, contents)), mapWorkspaceError, Effect.as({ written: true }))
68
+ }),
69
+ makeTool({
70
+ name: "workspace_append",
71
+ description: "Append bounded UTF-8 content under the workspace root",
72
+ parameters: contentSchema,
73
+ tags: ["file", "append", "workspace"],
74
+ execute: (parameters) => Effect.all({
75
+ path: parameter(parameters, "path"),
76
+ contents: parameter(parameters, "contents")
77
+ }).pipe(Effect.flatMap(({ path, contents }) => workspace.append(path, contents)), mapWorkspaceError, Effect.as({ appended: true }))
78
+ }),
79
+ makeTool({
80
+ name: "workspace_discover",
81
+ description: "Discover files under the workspace root using a bounded glob",
82
+ parameters: {
83
+ type: "object",
84
+ properties: {
85
+ pattern: { type: "string" }
86
+ },
87
+ additionalProperties: false
88
+ },
89
+ tags: ["file", "glob", "discover", "workspace"],
90
+ sandbox: "WorkspaceReadOnly",
91
+ execute: (parameters) => optionalParameter(parameters, "pattern").pipe(Effect.flatMap((pattern) => workspace.discover(pattern)), mapWorkspaceError, Effect.map((paths) => [...paths]))
92
+ }),
93
+ makeTool({
94
+ name: "workspace_search",
95
+ description: "Search bounded workspace files for literal text",
96
+ parameters: {
97
+ type: "object",
98
+ properties: {
99
+ query: { type: "string" },
100
+ pattern: { type: "string" }
101
+ },
102
+ required: ["query"],
103
+ additionalProperties: false
104
+ },
105
+ tags: ["file", "search", "workspace"],
106
+ sandbox: "WorkspaceReadOnly",
107
+ execute: (parameters) => Effect.all({
108
+ query: parameter(parameters, "query"),
109
+ pattern: optionalParameter(parameters, "pattern")
110
+ }).pipe(Effect.flatMap(({ pattern, query }) => workspace.search(query, pattern)), mapWorkspaceError, Effect.map((matches) => matches.map((match) => ({
111
+ path: match.path,
112
+ line: match.line,
113
+ text: match.text
114
+ }))))
115
+ }),
116
+ makeTool({
117
+ name: "workspace_validate_json",
118
+ description: "Validate that a bounded workspace file contains JSON",
119
+ parameters: pathSchema,
120
+ tags: ["file", "validate", "json", "workspace"],
121
+ sandbox: "WorkspaceReadOnly",
122
+ execute: (parameters) => parameter(parameters, "path").pipe(Effect.flatMap((path) => workspace.read(path)), mapWorkspaceError, Effect.flatMap((contents) => Effect.try({
123
+ try: () => JSON.parse(contents),
124
+ catch: (error) => ToolExecutionFailed.make({
125
+ message: `invalid JSON: ${String(error)}`
126
+ })
127
+ })), Effect.as({ valid: true }))
128
+ })
129
+ ];
130
+ //# sourceMappingURL=WorkspaceTools.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WorkspaceTools.js","sourceRoot":"","sources":["../src/WorkspaceTools.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,91 @@
1
+ {
2
+ "name": "@llm4ts/flow",
3
+ "version": "0.1.0",
4
+ "description": "Effect-native LLM workflow, persistence, review, and repository automation",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "sideEffects": false,
8
+ "engines": {
9
+ "node": ">=22"
10
+ },
11
+ "files": [
12
+ "dist",
13
+ "src"
14
+ ],
15
+ "exports": {
16
+ "./package.json": "./package.json",
17
+ "./AzureDevOpsTool": "./dist/AzureDevOpsTool.js",
18
+ "./Bench": "./dist/Bench.js",
19
+ "./BenchReport": "./dist/BenchReport.js",
20
+ "./CapabilityGuard": "./dist/CapabilityGuard.js",
21
+ "./Chat": "./dist/Chat.js",
22
+ "./Classified": "./dist/Classified.js",
23
+ "./CostLedger": "./dist/CostLedger.js",
24
+ "./CostTracker": "./dist/CostTracker.js",
25
+ "./Equiv": "./dist/Equiv.js",
26
+ "./EquivReport": "./dist/EquivReport.js",
27
+ "./Flow": "./dist/Flow.js",
28
+ "./FlowContext": "./dist/FlowContext.js",
29
+ "./FlowError": "./dist/FlowError.js",
30
+ "./FlowEvents": "./dist/FlowEvents.js",
31
+ "./FlowRecorder": "./dist/FlowRecorder.js",
32
+ "./GitHubTool": "./dist/GitHubTool.js",
33
+ "./GitTool": "./dist/GitTool.js",
34
+ "./Interaction": "./dist/Interaction.js",
35
+ "./McpServer": "./dist/McpServer.js",
36
+ "./Mermaid": "./dist/Mermaid.js",
37
+ "./Pack": "./dist/Pack.js",
38
+ "./Package": "./dist/Package.js",
39
+ "./Persistence": "./dist/Persistence.js",
40
+ "./Plan": "./dist/Plan.js",
41
+ "./PlanExecution": "./dist/PlanExecution.js",
42
+ "./Planner": "./dist/Planner.js",
43
+ "./PrSummary": "./dist/PrSummary.js",
44
+ "./PriceList": "./dist/PriceList.js",
45
+ "./Provenance": "./dist/Provenance.js",
46
+ "./Replay": "./dist/Replay.js",
47
+ "./Review": "./dist/Review.js",
48
+ "./ReviewCache": "./dist/ReviewCache.js",
49
+ "./Reviewer": "./dist/Reviewer.js",
50
+ "./SpecChecks": "./dist/SpecChecks.js",
51
+ "./Survey": "./dist/Survey.js",
52
+ "./TransientRetry": "./dist/TransientRetry.js",
53
+ "./Workspace": "./dist/Workspace.js",
54
+ "./WorkspaceLayout": "./dist/WorkspaceLayout.js",
55
+ "./WorkspaceTools": "./dist/WorkspaceTools.js"
56
+ },
57
+ "publishConfig": {
58
+ "access": "public",
59
+ "provenance": true
60
+ },
61
+ "repository": {
62
+ "type": "git",
63
+ "url": "git+https://github.com/riccardomerolla/llm4ts.git",
64
+ "directory": "packages/flow"
65
+ },
66
+ "homepage": "https://github.com/riccardomerolla/llm4ts#readme",
67
+ "bugs": {
68
+ "url": "https://github.com/riccardomerolla/llm4ts/issues"
69
+ },
70
+ "keywords": [
71
+ "llm",
72
+ "effect",
73
+ "ai",
74
+ "agents",
75
+ "workflow",
76
+ "typescript"
77
+ ],
78
+ "dependencies": {
79
+ "@llm4ts/core": "0.1.0"
80
+ },
81
+ "peerDependencies": {
82
+ "effect": "^4.0.0-beta.102"
83
+ },
84
+ "devDependencies": {
85
+ "effect": "^4.0.0-beta.102"
86
+ },
87
+ "scripts": {
88
+ "clean": "tsc -b tsconfig.json --clean",
89
+ "test": "vitest run test"
90
+ }
91
+ }
@@ -0,0 +1,291 @@
1
+ import * as Duration from "effect/Duration"
2
+ import * as Effect from "effect/Effect"
3
+ import * as Redacted from "effect/Redacted"
4
+ import * as Schema from "effect/Schema"
5
+ import { Capabilities } from "@llm4ts/core/Capability"
6
+ import type { HttpClientShape } from "@llm4ts/core/HttpClient"
7
+ import type { JsonValue } from "@llm4ts/core/providers/CliSupport"
8
+ import { ProcessError, type FlowError } from "./FlowError.ts"
9
+ import type { FlowEventsShape } from "./FlowEvents.ts"
10
+ import { guarded } from "./CapabilityGuard.ts"
11
+
12
+ export class AdoRequest extends Schema.Class<AdoRequest>("AdoRequest")({
13
+ method: Schema.String,
14
+ url: Schema.String,
15
+ body: Schema.optionalKey(Schema.String),
16
+ contentType: Schema.String.pipe(Schema.withConstructorDefault(Effect.succeed("application/json")))
17
+ }) {}
18
+
19
+ export class WorkItem extends Schema.Class<WorkItem>("WorkItem")({
20
+ id: Schema.Int,
21
+ title: Schema.String,
22
+ description: Schema.String,
23
+ acceptanceCriteria: Schema.String,
24
+ state: Schema.String,
25
+ tags: Schema.Array(Schema.String)
26
+ }) {}
27
+
28
+ export class AdoPullRequest extends Schema.Class<AdoPullRequest>("AdoPullRequest")({
29
+ id: Schema.Int,
30
+ repoId: Schema.String,
31
+ projectId: Schema.String,
32
+ webUrl: Schema.String
33
+ }) {}
34
+
35
+ export class AdoConfig extends Schema.Class<AdoConfig>("AdoConfig")({
36
+ orgUrl: Schema.String,
37
+ project: Schema.String,
38
+ repository: Schema.String,
39
+ pat: Schema.Redacted(Schema.String, {
40
+ disallowJsonEncode: true
41
+ }),
42
+ apiVersion: Schema.String.pipe(Schema.withConstructorDefault(Effect.succeed("7.1")))
43
+ }) {}
44
+
45
+ const encodeBase64 = (value: string): string => {
46
+ const alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
47
+ const bytes = new TextEncoder().encode(value)
48
+ let encoded = ""
49
+ for (let index = 0; index < bytes.length; index += 3) {
50
+ const first = bytes[index] ?? 0
51
+ const second = bytes[index + 1]
52
+ const third = bytes[index + 2]
53
+ const bits = (first << 16) | ((second ?? 0) << 8) | (third ?? 0)
54
+ encoded += alphabet[(bits >>> 18) & 63] ?? ""
55
+ encoded += alphabet[(bits >>> 12) & 63] ?? ""
56
+ encoded += second === undefined ? "=" : (alphabet[(bits >>> 6) & 63] ?? "")
57
+ encoded += third === undefined ? "=" : (alphabet[bits & 63] ?? "")
58
+ }
59
+ return encoded
60
+ }
61
+
62
+ export const authorizationHeader = (config: AdoConfig): Readonly<Record<string, string>> => ({
63
+ Authorization: `Basic ${encodeBase64(`:${Redacted.value(config.pat)}`)}`
64
+ })
65
+
66
+ const witBase = (config: AdoConfig): string => `${config.orgUrl}/${config.project}/_apis/wit`
67
+ const gitBase = (config: AdoConfig): string =>
68
+ `${config.orgUrl}/${config.project}/_apis/git/repositories/${config.repository}`
69
+
70
+ const patchOperations = (fields: Readonly<Record<string, string>>): ReadonlyArray<JsonValue> =>
71
+ Object.entries(fields).map(([name, value]) => ({
72
+ op: "add",
73
+ path: `/fields/${name}`,
74
+ value
75
+ }))
76
+
77
+ export const readWorkItemRequest = (config: AdoConfig, id: number): AdoRequest =>
78
+ AdoRequest.make({
79
+ method: "GET",
80
+ url: `${witBase(config)}/workitems/${id}?$expand=relations&api-version=${config.apiVersion}`
81
+ })
82
+
83
+ export const wiqlRequest = (config: AdoConfig, query: string): AdoRequest =>
84
+ AdoRequest.make({
85
+ method: "POST",
86
+ url: `${witBase(config)}/wiql?api-version=${config.apiVersion}`,
87
+ body: JSON.stringify({ query })
88
+ })
89
+
90
+ export const setFieldsRequest = (
91
+ config: AdoConfig,
92
+ id: number,
93
+ fields: Readonly<Record<string, string>>
94
+ ): AdoRequest =>
95
+ AdoRequest.make({
96
+ method: "PATCH",
97
+ url: `${witBase(config)}/workitems/${id}?api-version=${config.apiVersion}`,
98
+ body: JSON.stringify(patchOperations(fields)),
99
+ contentType: "application/json-patch+json"
100
+ })
101
+
102
+ export const createPullRequestRequest = (
103
+ config: AdoConfig,
104
+ sourceRef: string,
105
+ targetRef: string,
106
+ title: string,
107
+ description: string
108
+ ): AdoRequest =>
109
+ AdoRequest.make({
110
+ method: "POST",
111
+ url: `${gitBase(config)}/pullrequests?api-version=${config.apiVersion}`,
112
+ body: JSON.stringify({
113
+ sourceRefName: sourceRef,
114
+ targetRefName: targetRef,
115
+ title,
116
+ description
117
+ })
118
+ })
119
+
120
+ const field = (fields: Readonly<Record<string, JsonValue>>, name: string): string => {
121
+ const value = fields[name]
122
+ return typeof value === "string" ? value : ""
123
+ }
124
+
125
+ export const parseWorkItem = (json: string): Effect.Effect<WorkItem, ProcessError> =>
126
+ Schema.decodeUnknownEffect(
127
+ Schema.fromJsonString(
128
+ Schema.Struct({
129
+ id: Schema.Int,
130
+ fields: Schema.Record(Schema.String, Schema.Json)
131
+ })
132
+ )
133
+ )(json).pipe(
134
+ Effect.map((item) => {
135
+ const tags = field(item.fields, "System.Tags")
136
+ .split(";")
137
+ .map((tag) => tag.trim())
138
+ .filter((tag) => tag.length > 0)
139
+ return WorkItem.make({
140
+ id: item.id,
141
+ title: field(item.fields, "System.Title"),
142
+ description: field(item.fields, "System.Description"),
143
+ acceptanceCriteria: field(item.fields, "Microsoft.VSTS.Common.AcceptanceCriteria"),
144
+ state: field(item.fields, "System.State"),
145
+ tags
146
+ })
147
+ }),
148
+ Effect.mapError((error) =>
149
+ ProcessError.make({
150
+ message: "ado parse work item",
151
+ detail: String(error)
152
+ })
153
+ )
154
+ )
155
+
156
+ export const parseWiqlIds = (json: string): Effect.Effect<ReadonlyArray<number>, ProcessError> =>
157
+ Schema.decodeUnknownEffect(
158
+ Schema.fromJsonString(
159
+ Schema.Struct({
160
+ workItems: Schema.Array(
161
+ Schema.Struct({
162
+ id: Schema.Int
163
+ })
164
+ )
165
+ })
166
+ )
167
+ )(json).pipe(
168
+ Effect.map((result) => result.workItems.map((item) => item.id)),
169
+ Effect.mapError((error) =>
170
+ ProcessError.make({
171
+ message: "ado parse wiql",
172
+ detail: String(error)
173
+ })
174
+ )
175
+ )
176
+
177
+ export const parsePullRequest = (
178
+ config: AdoConfig,
179
+ json: string
180
+ ): Effect.Effect<AdoPullRequest, ProcessError> =>
181
+ Schema.decodeUnknownEffect(
182
+ Schema.fromJsonString(
183
+ Schema.Struct({
184
+ pullRequestId: Schema.Int,
185
+ repository: Schema.Struct({
186
+ id: Schema.String,
187
+ project: Schema.Struct({
188
+ id: Schema.String
189
+ })
190
+ })
191
+ })
192
+ )
193
+ )(json).pipe(
194
+ Effect.map((result) =>
195
+ AdoPullRequest.make({
196
+ id: result.pullRequestId,
197
+ repoId: result.repository.id,
198
+ projectId: result.repository.project.id,
199
+ webUrl:
200
+ `${config.orgUrl}/${config.project}/_git/` +
201
+ `${config.repository}/pullrequest/${result.pullRequestId}`
202
+ })
203
+ ),
204
+ Effect.mapError((error) =>
205
+ ProcessError.make({
206
+ message: "ado parse pull request",
207
+ detail: String(error)
208
+ })
209
+ )
210
+ )
211
+
212
+ export interface AzureDevOpsToolShape {
213
+ readonly readWorkItem: (id: number) => Effect.Effect<WorkItem, FlowError>
214
+ readonly wiqlIds: (query: string) => Effect.Effect<ReadonlyArray<number>, FlowError>
215
+ readonly setFields: (
216
+ id: number,
217
+ fields: Readonly<Record<string, string>>
218
+ ) => Effect.Effect<void, FlowError>
219
+ readonly setState: (id: number, state: string) => Effect.Effect<void, FlowError>
220
+ readonly setAcceptanceCriteria: (id: number, text: string) => Effect.Effect<void, FlowError>
221
+ readonly createPr: (
222
+ sourceRef: string,
223
+ targetRef: string,
224
+ title: string,
225
+ body: string
226
+ ) => Effect.Effect<AdoPullRequest, FlowError>
227
+ }
228
+
229
+ export const makeAzureDevOpsTool = (
230
+ config: AdoConfig,
231
+ http: HttpClientShape,
232
+ events: FlowEventsShape,
233
+ timeout: Duration.Duration = Duration.seconds(30)
234
+ ): AzureDevOpsToolShape => {
235
+ const run = (request: AdoRequest): Effect.Effect<string, FlowError> =>
236
+ http
237
+ .send(
238
+ request.method,
239
+ request.url,
240
+ request.body,
241
+ authorizationHeader(config),
242
+ request.contentType,
243
+ timeout
244
+ )
245
+ .pipe(
246
+ Effect.mapError((error) =>
247
+ ProcessError.make({
248
+ message: `ado ${request.method} ${request.url}`,
249
+ detail: error.message
250
+ })
251
+ )
252
+ )
253
+
254
+ const read = <A>(
255
+ operation: string,
256
+ effect: Effect.Effect<A, FlowError>
257
+ ): Effect.Effect<A, FlowError> => guarded(Capabilities.AdoRead, operation, events, effect)
258
+ const write = <A>(
259
+ operation: string,
260
+ effect: Effect.Effect<A, FlowError>
261
+ ): Effect.Effect<A, FlowError> => guarded(Capabilities.AdoWrite, operation, events, effect)
262
+
263
+ const setFields = (
264
+ id: number,
265
+ fields: Readonly<Record<string, string>>
266
+ ): Effect.Effect<void, FlowError> =>
267
+ write("ado setFields", run(setFieldsRequest(config, id, fields)).pipe(Effect.asVoid))
268
+
269
+ return {
270
+ readWorkItem: (id) =>
271
+ read(
272
+ "ado readWorkItem",
273
+ run(readWorkItemRequest(config, id)).pipe(Effect.flatMap(parseWorkItem))
274
+ ),
275
+ wiqlIds: (query) =>
276
+ read("ado wiql", run(wiqlRequest(config, query)).pipe(Effect.flatMap(parseWiqlIds))),
277
+ setFields,
278
+ setState: (id, state) => setFields(id, { "System.State": state }),
279
+ setAcceptanceCriteria: (id, text) =>
280
+ setFields(id, {
281
+ "Microsoft.VSTS.Common.AcceptanceCriteria": text
282
+ }),
283
+ createPr: (sourceRef, targetRef, title, body) =>
284
+ write(
285
+ "ado createPr",
286
+ run(createPullRequestRequest(config, sourceRef, targetRef, title, body)).pipe(
287
+ Effect.flatMap((json) => parsePullRequest(config, json))
288
+ )
289
+ )
290
+ }
291
+ }