@krak-stack/registry 0.1.38 → 0.1.40

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 (38) hide show
  1. package/README.md +106 -29
  2. package/dist/components/ui/app-brand.js +17 -17
  3. package/dist/components/ui/code-block.js +4 -4
  4. package/dist/components/ui/copy-button.js +2 -2
  5. package/dist/components/ui/data-table.js +55 -55
  6. package/dist/components/ui/editing-locale-switcher.js +8 -8
  7. package/dist/components/ui/effect-form.js +12 -12
  8. package/dist/components/ui/error-component.js +6 -6
  9. package/dist/components/ui/file-picker.js +2 -2
  10. package/dist/components/ui/form.js +24 -24
  11. package/dist/components/ui/icon-input.js +5 -5
  12. package/dist/components/ui/locale-switcher.js +2 -2
  13. package/dist/components/ui/search-menu.js +2 -2
  14. package/dist/components/ui/sidebar-layout.js +1 -1
  15. package/dist/components/ui/theme-switcher.js +3 -3
  16. package/dist/lib/docs.js +52 -111
  17. package/dist/lib/docs.server.js +0 -28
  18. package/dist/lib/documentation-toolkit.js +0 -28
  19. package/dist/lib/httpapi-adapter.d.ts +73 -0
  20. package/dist/lib/httpapi-adapter.js +189 -0
  21. package/dist/lib/httpapi-cli.d.ts +4 -22
  22. package/dist/lib/httpapi-cli.js +199 -313
  23. package/dist/lib/httpapi-toolkit.d.ts +7 -16
  24. package/dist/lib/httpapi-toolkit.js +158 -214
  25. package/dist/lib/query.d.ts +30 -3
  26. package/dist/lib/query.js +13 -3
  27. package/dist/lib/webfetch-toolkit.d.ts +1 -1
  28. package/dist/lib/webfetch-toolkit.js +48 -50
  29. package/dist/oxlint/anti-slop/index.js +2 -2
  30. package/dist/services/agent/client/index.js +6 -6
  31. package/dist/services/agent/index.js +2 -2
  32. package/package.json +4 -12
  33. package/dist/lib/httpapi-client.d.ts +0 -34
  34. package/dist/lib/httpapi-client.js +0 -122
  35. package/dist/lib/httpapi-helpers.d.ts +0 -79
  36. package/dist/lib/httpapi-helpers.js +0 -130
  37. package/dist/lib/httpapi-mcp.d.ts +0 -25
  38. package/dist/lib/httpapi-mcp.js +0 -321
@@ -1,39 +1,44 @@
1
1
  // ../../src/lib/httpapi-cli.ts
2
- import {
3
- Cause,
4
- Console,
5
- Context as Context3,
6
- Effect as Effect3,
7
- Exit,
8
- FileSystem,
9
- Layer as Layer3,
10
- Option as Option2,
11
- Path,
12
- Schema as Schema3,
13
- Stdio,
14
- Stream,
15
- Terminal
16
- } from "effect";
2
+ import { Console, Effect as Effect2, Option as Option2, Schema as Schema2, Stream } from "effect";
17
3
  import { Argument, Command, Flag } from "effect/cli";
18
- import { ChildProcessSpawner } from "effect/process/ChildProcessSpawner";
19
4
 
20
- // ../../src/lib/httpapi-client.ts
21
- import { Context, Effect, Layer, Schema, SchemaTransformation } from "effect";
22
- import { HttpClient } from "effect/http";
5
+ // ../../src/lib/httpapi-adapter.ts
23
6
  import {
24
- HttpApi,
25
- HttpApiClient as EffectHttpApiClient,
26
- OpenApi
27
- } from "effect/http-api";
28
- var executeHttpApiOperation = Effect.fn("HttpApiClient.executeOperation")((options, client) => client.execute({
29
- operation: options.operation,
30
- input: {
31
- body: options.input.body,
32
- headers: options.input.headers ?? {},
33
- params: options.input.params ?? {},
34
- query: options.input.query ?? {}
35
- }
36
- }));
7
+ Context,
8
+ Effect,
9
+ Layer,
10
+ Option,
11
+ Schema,
12
+ SchemaTransformation
13
+ } from "effect";
14
+ import { HttpClient } from "effect/http";
15
+ import { HttpApi, HttpApiClient, OpenApi } from "effect/http-api";
16
+ var HttpApiMethods = [
17
+ "get",
18
+ "post",
19
+ "put",
20
+ "patch",
21
+ "delete"
22
+ ];
23
+ var HttpApiOperation = Schema.Struct({
24
+ operationId: Schema.optional(Schema.String),
25
+ summary: Schema.optional(Schema.String),
26
+ description: Schema.optional(Schema.String),
27
+ tags: Schema.optional(Schema.Array(Schema.String)),
28
+ parameters: Schema.optional(Schema.Array(Schema.Struct({
29
+ name: Schema.String,
30
+ in: Schema.Literals(["path", "query", "header", "cookie"]),
31
+ required: Schema.optional(Schema.Boolean),
32
+ description: Schema.optional(Schema.String),
33
+ schema: Schema.optional(Schema.Json)
34
+ }))),
35
+ requestBody: Schema.optional(Schema.Struct({
36
+ required: Schema.optional(Schema.Boolean),
37
+ content: Schema.optional(Schema.Record(Schema.String, Schema.Struct({
38
+ schema: Schema.optional(Schema.Json)
39
+ })))
40
+ }))
41
+ }).annotate({ identifier: "HttpApiOperation" });
37
42
  var UndefinedFromNull = Schema.Null.pipe(Schema.decodeTo(Schema.Undefined, SchemaTransformation.transform({
38
43
  decode: () => {
39
44
  return;
@@ -55,238 +60,163 @@ var HttpApiOperationResult = Schema.Union([
55
60
  HttpApiOperationResultValue,
56
61
  Schema.Undefined
57
62
  ]).annotate({ identifier: "HttpApiOperationResult" });
58
- var encodeHttpApiOperationResult = Effect.fn("HttpApiClient.encodeOperationResult")((result) => Schema.encodeUnknownEffect(HttpApiOperationResult)(result).pipe(Effect.map((encoded) => encoded ?? null), Effect.mapError((cause) => new Error("HTTP API result is not serializable", { cause }))));
63
+ var encodeHttpApiOperationResult = Effect.fn("HttpApiAdapter.encodeOperationResult")((result) => Schema.encodeUnknownEffect(HttpApiOperationResult)(result).pipe(Effect.map((encoded) => encoded ?? null), Effect.mapError((cause) => new Error("HTTP API result is not serializable", { cause }))));
64
+ var encodeOperationResult = Effect.fn("HttpApiAdapter.encodeResult")((result, operation) => operation.successSchema ? Schema.encodeUnknownEffect(operation.successSchema)(result).pipe(Effect.flatMap(encodeHttpApiOperationResult), Effect.mapError((cause) => new Error("HTTP API result does not match its success schema", {
65
+ cause
66
+ }))) : encodeHttpApiOperationResult(result));
59
67
  var reflectedSchema = (schema) => Schema.make(schema.ast);
60
- var operationResultSchemas = (api) => {
61
- const schemas = new Map;
62
- HttpApi.reflect(api, {
63
- onGroup: () => {
64
- return;
65
- },
66
- onEndpoint: ({ endpoint, group, successes }) => {
67
- const operationId = Context.getOrElse(endpoint.annotations, OpenApi.Identifier, () => group.topLevel ? endpoint.identifier : `${group.identifier}.${endpoint.identifier}`);
68
- const operationSchemas = Array.from(successes.values()).flat().map(reflectedSchema);
69
- if (operationSchemas.length === 1 && operationSchemas[0]) {
70
- schemas.set(operationId, operationSchemas[0]);
71
- } else if (operationSchemas.length > 1) {
72
- schemas.set(operationId, Schema.Union(operationSchemas));
68
+ var sanitizeHttpName = (name) => name.replace(/[^a-zA-Z0-9_-]/g, "_").replace(/_+/g, "_").replace(/^_+|_+$/g, "");
69
+ var httpApiToolName = (entry) => (entry.operation.operationId || `${entry.method}_${entry.path.replace(/^\/api\//, "").replace(/[/:{}]/g, "_")}`).replace(/[^a-zA-Z0-9_-]/g, "_").replace(/_+/g, "_").slice(0, 64);
70
+ var makeCatalogue = (api, methods, include) => Effect.try({
71
+ try: () => {
72
+ if (!HttpApi.isHttpApi(api))
73
+ throw new Error("HttpApiAdapter requires a valid HttpApi");
74
+ const spec = OpenApi.fromApi(api);
75
+ const reflected = new Map;
76
+ HttpApi.reflect(api, {
77
+ onGroup: () => {
78
+ return;
79
+ },
80
+ onEndpoint: ({ endpoint, group, successes }) => {
81
+ const operationId = Context.getOrElse(endpoint.annotations, OpenApi.Identifier, () => group.topLevel ? endpoint.identifier : `${group.identifier}.${endpoint.identifier}`);
82
+ if (reflected.has(operationId))
83
+ throw new Error(`Duplicate HTTP API operation ID: ${operationId}`);
84
+ const fields = {};
85
+ if (endpoint.params)
86
+ fields.params = Schema.toType(reflectedSchema(endpoint.params));
87
+ if (endpoint.query)
88
+ fields.query = Schema.optionalKey(Schema.toType(reflectedSchema(endpoint.query)));
89
+ if (endpoint.headers)
90
+ fields.headers = Schema.optionalKey(Schema.toType(reflectedSchema(endpoint.headers)));
91
+ const payloads = Array.from(endpoint.payload.values()).flatMap(({ schemas }) => schemas.map(reflectedSchema));
92
+ if (payloads.length === 1 && payloads[0])
93
+ fields.body = payloads[0];
94
+ else if (payloads.length > 1)
95
+ fields.body = Schema.Union(payloads);
96
+ const input = Object.keys(fields).length === 0 ? Schema.Record(Schema.String, Schema.Never) : Schema.Struct(fields);
97
+ const inputSchema = Schema.make(Schema.toCodecJson(input).ast).annotate({
98
+ identifier: `${sanitizeHttpName(operationId)}ToolInput`
99
+ });
100
+ const successSchemas = Array.from(successes.values()).flat().map(reflectedSchema);
101
+ reflected.set(operationId, {
102
+ groupIdentifier: group.identifier,
103
+ endpointIdentifier: endpoint.identifier,
104
+ topLevel: group.topLevel,
105
+ inputSchema,
106
+ successSchema: successSchemas.length === 1 ? successSchemas[0] : successSchemas.length > 1 ? Schema.Union(successSchemas) : undefined
107
+ });
108
+ }
109
+ });
110
+ const names = new Set;
111
+ const operations = [];
112
+ for (const [path, pathItem] of Object.entries(spec.paths)) {
113
+ for (const method of methods) {
114
+ const decoded = Schema.decodeUnknownOption(HttpApiOperation)(pathItem[method]);
115
+ if (Option.isNone(decoded))
116
+ continue;
117
+ const entry = { method, path, operation: decoded.value };
118
+ if (include && !include(entry))
119
+ continue;
120
+ const metadata = entry.operation.operationId ? reflected.get(entry.operation.operationId) : undefined;
121
+ if (!metadata)
122
+ throw new Error(`Missing endpoint schema for ${entry.operation.operationId}`);
123
+ const name = httpApiToolName(entry);
124
+ if (!name || names.has(name))
125
+ throw new Error(`Duplicate or empty HTTP API tool name: ${name}`);
126
+ names.add(name);
127
+ const document = Schema.toJsonSchemaDocument(metadata.inputSchema.annotate({ identifier: undefined }));
128
+ operations.push({
129
+ ...entry,
130
+ ...metadata,
131
+ name,
132
+ inputJsonSchema: {
133
+ ...document.schema,
134
+ $defs: document.definitions
135
+ },
136
+ readOnly: method === "get",
137
+ destructive: method === "delete",
138
+ idempotent: method === "get" || method === "put" || method === "delete"
139
+ });
73
140
  }
74
141
  }
75
- });
76
- return schemas;
77
- };
78
- var makeHttpApiOperationResultEncoder = (api) => {
79
- const schemas = operationResultSchemas(api);
80
- return Effect.fn("HttpApiClient.encodeOperationResultWithSchema")((result, operation) => {
81
- const operationId = operation.operation.operationId;
82
- const schema = operationId ? schemas.get(operationId) : undefined;
83
- if (!schema)
84
- return encodeHttpApiOperationResult(result);
85
- return Schema.encodeUnknownEffect(schema)(result).pipe(Effect.flatMap(encodeHttpApiOperationResult), Effect.mapError((cause) => new Error("HTTP API result does not match its success schema", {
86
- cause
87
- })));
88
- });
89
- };
142
+ return { info: spec.info, operations };
143
+ },
144
+ catch: (cause) => new Error("Failed to build HTTP API adapter catalogue", { cause })
145
+ });
90
146
  var GeneratedOperation = Schema.declare((value) => value instanceof Function).annotate({ identifier: "GeneratedOperation" });
91
147
  var GeneratedOperationEffect = Schema.declare((value) => Effect.isEffect(value)).annotate({ identifier: "GeneratedOperationEffect" });
92
- var makeGeneratedClient = (api, http, baseUrl) => EffectHttpApiClient.makeWith(api, {
93
- baseUrl,
94
- httpClient: http
95
- });
96
- var executeGeneratedOperation = Effect.fn("HttpApiClient.executeGeneratedOperation")(function* (client, { input, operation: entry }) {
97
- const operationId = entry.operation.operationId;
98
- if (!operationId) {
99
- return yield* Effect.fail(new Error(`No generated API client operation for ${entry.method} ${entry.path}`));
100
- }
101
- const target = Object(client);
102
- const groupName = Object.keys(target).filter((name) => operationId.startsWith(`${name}.`)).sort((a, b) => b.length - a.length)[0];
103
- const group = groupName ? Object.entries(target).find(([name]) => name === groupName)?.[1] : target;
104
- const endpointName = groupName ? operationId.slice(groupName.length + 1) : operationId;
105
- const endpointCandidate = group instanceof Function ? undefined : Object.entries(Object(group)).find(([name]) => name === endpointName)?.[1];
106
- const endpoint = Schema.decodeUnknownOption(GeneratedOperation)(endpointCandidate);
107
- if (endpoint._tag === "None") {
108
- return yield* Effect.fail(new Error(`No generated API client operation for ${operationId}`));
109
- }
148
+ var executeGeneratedOperation = Effect.fn("HttpApiAdapter.executeGeneratedOperation")(function* (client, { operation, input }) {
149
+ const group = operation.topLevel ? client : Object.entries(Object(client)).find(([name]) => name === operation.groupIdentifier)?.[1];
150
+ const candidate = Object.entries(Object(group)).find(([name]) => name === operation.endpointIdentifier)?.[1];
151
+ const endpoint = Schema.decodeUnknownOption(GeneratedOperation)(candidate);
152
+ if (Option.isNone(endpoint))
153
+ return yield* Effect.fail(new Error(`No generated API client operation for ${operation.operation.operationId}`));
110
154
  const result = Schema.decodeUnknownOption(GeneratedOperationEffect)(endpoint.value({
111
- headers: input.headers,
112
- params: input.params,
113
- query: input.query,
155
+ headers: input.headers ?? {},
156
+ params: input.params ?? {},
157
+ query: input.query ?? {},
114
158
  payload: input.body
115
159
  }));
116
- if (result._tag === "None") {
117
- return yield* Effect.fail(new Error(`Generated API client operation ${operationId} is invalid`));
118
- }
160
+ if (Option.isNone(result))
161
+ return yield* Effect.fail(new Error(`Generated API client operation ${operation.operation.operationId} is invalid`));
119
162
  return yield* result.value;
120
163
  });
121
164
 
122
- class ApiClient extends Context.Service()("ApiClient") {
123
- static layer = (config) => Layer.effect(this, Effect.gen(function* () {
124
- const http = yield* HttpClient.HttpClient;
125
- const encodeResult = makeHttpApiOperationResultEncoder(config.api);
126
- const client = yield* makeGeneratedClient(config.api, http, config.baseUrl);
127
- return {
128
- encodeResult: config.encodeResult ?? ((result, operation) => encodeResult(result, operation)),
129
- execute: Effect.fn("ApiClient.execute")(function* (options) {
130
- return yield* executeGeneratedOperation(client, options);
165
+ class HttpApiAdapter extends Context.Service()("@krak-stack/registry/HttpApiAdapter") {
166
+ static make = Effect.fn("HttpApiAdapter.make")(function* (config) {
167
+ const catalogue = yield* makeCatalogue(config.api, config.methods ?? HttpApiMethods, config.include);
168
+ const httpClient = yield* HttpClient.HttpClient;
169
+ const client = yield* HttpApiClient.makeWith(config.api, {
170
+ baseUrl: config.baseUrl,
171
+ httpClient
172
+ });
173
+ return HttpApiAdapter.of({
174
+ ...catalogue,
175
+ encodeResult: config.encodeResult ?? encodeOperationResult,
176
+ execute: Effect.fn("HttpApiAdapter.execute")(function* (options) {
177
+ const operation = catalogue.operations.find((entry) => entry.method === options.operation.method && entry.path === options.operation.path && entry.operation.operationId === options.operation.operation.operationId);
178
+ if (!operation) {
179
+ return yield* Effect.fail(new Error("Operation is not in this HTTP API adapter catalogue"));
180
+ }
181
+ return yield* executeGeneratedOperation(client, {
182
+ operation,
183
+ input: options.input
184
+ });
131
185
  })
132
- };
133
- }));
134
- }
135
-
136
- // ../../src/lib/httpapi-helpers.tsx
137
- import { Context as Context2, Effect as Effect2, Layer as Layer2, Option, Schema as Schema2 } from "effect";
138
- import { HttpApi as HttpApi2, OpenApi as OpenApi2 } from "effect/http-api";
139
- var JsonObjectSchema = Schema2.Record(Schema2.String, Schema2.Json).annotate({
140
- identifier: "HttpJsonObject",
141
- title: "HTTP JSON object",
142
- description: "A JSON object passed to an HTTP API operation.",
143
- examples: [{ id: "example-id" }]
144
- });
145
- var JsonObjectFromString = Schema2.fromJsonString(JsonObjectSchema);
146
- var JsonValueFromString = Schema2.fromJsonString(Schema2.Json);
147
- var HttpApiMethods = [
148
- "get",
149
- "post",
150
- "put",
151
- "patch",
152
- "delete"
153
- ];
154
- var HttpApiOperationSchema = Schema2.declare((value) => Schema2.is(JsonObjectSchema)(value)).annotate({ identifier: "HttpApiOperation" });
155
- var decodeHttpApiOperation = Schema2.decodeUnknownOption(HttpApiOperationSchema);
156
- var toHttpError = (message, error) => new Error(message, { cause: error });
157
- var sanitizeHttpName = (name) => name.replace(/[^a-zA-Z0-9_-]/g, "_").replace(/_+/g, "_").replace(/^_+|_+$/g, "");
158
- var httpApiToolName = (method, path, operation) => {
159
- const fallback = `${method}_${path.replace(/^\/api\//, "").replace(/[/:{}]/g, "_")}`;
160
- return (operation.operationId || fallback).replace(/[^a-zA-Z0-9_-]/g, "_").replace(/_+/g, "_").slice(0, 64);
161
- };
162
- var httpApiOperations = ({
163
- spec,
164
- methods = HttpApiMethods
165
- }) => {
166
- const operations = [];
167
- for (const [path, pathItem] of Object.entries(spec.paths)) {
168
- for (const method of methods) {
169
- const operation = decodeHttpApiOperation(pathItem[method]);
170
- if (Option.isSome(operation))
171
- operations.push({ method, path, operation: operation.value });
172
- }
173
- }
174
- return operations;
175
- };
176
- var reflectedSchema2 = (schema) => Schema2.make(schema.ast);
177
- var reflectedOperationInputSchemas = (api) => {
178
- const schemas = new Map;
179
- HttpApi2.reflect(api, {
180
- onGroup: () => {
181
- return;
182
- },
183
- onEndpoint: ({ endpoint, group }) => {
184
- const operationId = Context2.getOrElse(endpoint.annotations, OpenApi2.Identifier, () => group.topLevel ? endpoint.identifier : `${group.identifier}.${endpoint.identifier}`);
185
- const fields = {};
186
- if (endpoint.params)
187
- fields.params = Schema2.toType(reflectedSchema2(endpoint.params));
188
- if (endpoint.query)
189
- fields.query = Schema2.optionalKey(Schema2.toType(reflectedSchema2(endpoint.query)));
190
- if (endpoint.headers)
191
- fields.headers = Schema2.optionalKey(Schema2.toType(reflectedSchema2(endpoint.headers)));
192
- const payloads = Array.from(endpoint.payload.values()).flatMap(({ schemas: schemas2 }) => schemas2.map(reflectedSchema2));
193
- if (payloads.length === 1 && payloads[0])
194
- fields.body = payloads[0];
195
- else if (payloads.length > 1)
196
- fields.body = Schema2.Union(payloads);
197
- const input = Object.keys(fields).length === 0 ? Schema2.Record(Schema2.String, Schema2.Never) : Schema2.Struct(fields);
198
- schemas.set(operationId, Schema2.make(Schema2.toCodecJson(input).ast).annotate({ identifier: `${sanitizeHttpName(operationId)}ToolInput` }));
199
- }
186
+ });
200
187
  });
201
- return schemas;
202
- };
203
- var parseJsonObject = Effect2.fn("Http.parseJsonObject")(function* (value, label) {
204
- if (!value)
205
- return {};
206
- return yield* Schema2.decodeUnknownEffect(JsonObjectFromString)(value).pipe(Effect2.mapError(() => new Error(`${label} must be a JSON object`)));
207
- });
208
- var parseJsonValue = Effect2.fn("Http.parseJsonValue")(function* (value, label) {
209
- if (!value)
210
- return;
211
- return yield* Schema2.decodeUnknownEffect(JsonValueFromString)(value).pipe(Effect2.mapError(() => new Error(`${label} must be valid JSON`)));
212
- });
213
-
214
- class HttpApiSpec extends Context2.Service()("HttpApiSpec", {
215
- make: (config) => Effect2.try({
216
- try: () => {
217
- const api = config.api;
218
- if (!HttpApi2.isHttpApi(api))
219
- throw new Error("HttpApiSpec requires a valid HttpApi");
220
- const spec = OpenApi2.fromApi(api);
221
- const schemas = reflectedOperationInputSchemas(api);
222
- const names = new Set;
223
- const operations = httpApiOperations({
224
- spec,
225
- methods: config.methods
226
- }).filter((entry) => config.include?.(entry) ?? true).map((entry) => {
227
- const name = httpApiToolName(entry.method, entry.path, entry.operation);
228
- if (!name || names.has(name))
229
- throw new Error(`Duplicate or empty HTTP API tool name: ${name}`);
230
- names.add(name);
231
- const inputSchema = entry.operation.operationId ? schemas.get(entry.operation.operationId) : undefined;
232
- if (!inputSchema)
233
- throw new Error(`Missing endpoint schema for ${entry.operation.operationId}`);
234
- const document = Schema2.toJsonSchemaDocument(inputSchema.annotate({ identifier: undefined }));
235
- return {
236
- ...entry,
237
- name,
238
- inputSchema,
239
- inputJsonSchema: {
240
- ...document.schema,
241
- $defs: document.definitions
242
- },
243
- readOnly: entry.method === "get",
244
- destructive: entry.method === "delete",
245
- idempotent: entry.method === "get" || entry.method === "put" || entry.method === "delete"
246
- };
247
- });
248
- return { info: spec.info, operations };
249
- },
250
- catch: (error) => toHttpError("Failed to build HTTP API spec", error)
251
- })
252
- }) {
253
- static layer = (config) => Layer2.effect(this, this.make(config));
188
+ static layer = (config) => Layer.effect(this, this.make(config));
254
189
  }
255
190
 
256
191
  // ../../src/lib/httpapi-cli.ts
257
- var CliJsonSchema = Schema3.Struct({
258
- type: Schema3.optional(Schema3.Union([Schema3.String, Schema3.Array(Schema3.String)])),
259
- description: Schema3.optional(Schema3.String),
260
- enum: Schema3.optional(Schema3.Array(Schema3.Json)),
261
- items: Schema3.optional(Schema3.Json),
262
- properties: Schema3.optional(Schema3.Record(Schema3.String, Schema3.Json)),
263
- required: Schema3.optional(Schema3.Array(Schema3.String)),
264
- pattern: Schema3.optional(Schema3.String),
265
- allOf: Schema3.optional(Schema3.Array(Schema3.Json)),
266
- anyOf: Schema3.optional(Schema3.Array(Schema3.Json)),
267
- $ref: Schema3.optional(Schema3.String),
268
- $defs: Schema3.optional(Schema3.Record(Schema3.String, Schema3.Json))
192
+ var CliJsonSchema = Schema2.Struct({
193
+ type: Schema2.optional(Schema2.Union([Schema2.String, Schema2.Array(Schema2.String)])),
194
+ description: Schema2.optional(Schema2.String),
195
+ enum: Schema2.optional(Schema2.Array(Schema2.Json)),
196
+ items: Schema2.optional(Schema2.Json),
197
+ properties: Schema2.optional(Schema2.Record(Schema2.String, Schema2.Json)),
198
+ required: Schema2.optional(Schema2.Array(Schema2.String)),
199
+ pattern: Schema2.optional(Schema2.String),
200
+ allOf: Schema2.optional(Schema2.Array(Schema2.Json)),
201
+ anyOf: Schema2.optional(Schema2.Array(Schema2.Json)),
202
+ $ref: Schema2.optional(Schema2.String),
203
+ $defs: Schema2.optional(Schema2.Record(Schema2.String, Schema2.Json))
269
204
  }).annotate({ identifier: "HttpApiCliJsonSchema" });
270
- var decodeCliJsonSchema = Schema3.decodeUnknownOption(CliJsonSchema);
271
- var JsonFromString = Schema3.fromJsonString(Schema3.Json);
272
- var CliParsedOption = Schema3.declare((value) => Option2.isOption(value) && Option2.match(value, {
205
+ var decodeCliJsonSchema = Schema2.decodeUnknownOption(CliJsonSchema);
206
+ var JsonFromString = Schema2.fromJsonString(Schema2.Json);
207
+ var CliParsedOption = Schema2.declare((value) => Option2.isOption(value) && Option2.match(value, {
273
208
  onNone: () => true,
274
- onSome: Schema3.is(Schema3.Json)
209
+ onSome: Schema2.is(Schema2.Json)
275
210
  })).annotate({ identifier: "HttpApiCliParsedOption" });
276
- var CliParsedConfig = Schema3.Record(Schema3.String, Schema3.Union([Schema3.Json, CliParsedOption])).annotate({ identifier: "HttpApiCliParsedConfig" });
277
-
278
- class HttpApiCli extends Context3.Service()("HttpApiCli", {
279
- make: () => Effect3.gen(function* () {
280
- const spec = yield* HttpApiSpec;
281
- const command = yield* makeHttpApiCliCommand();
282
- return {
283
- command,
284
- run: (args) => Command.runWith(command, { version: spec.info.version })(args)
285
- };
286
- })
287
- }) {
288
- static layer = Layer3.effect(this, this.make());
289
- }
211
+ var CliParsedConfig = Schema2.Record(Schema2.String, Schema2.Union([Schema2.Json, CliParsedOption])).annotate({ identifier: "HttpApiCliParsedConfig" });
212
+ var makeHttpApiCli = Effect2.fn("HttpApiCli.make")(function* () {
213
+ const spec = yield* HttpApiAdapter;
214
+ const command = yield* makeHttpApiCliCommand();
215
+ return {
216
+ command,
217
+ run: (args) => Command.runWith(command, { version: spec.info.version })(args)
218
+ };
219
+ });
290
220
  var toHttpApiCliName = (value) => value.replace(/([a-z0-9])([A-Z])/g, "$1-$2").replace(/([A-Z]+)([A-Z][a-z])/g, "$1-$2").replace(/[^a-zA-Z0-9]+/g, "-").replace(/^-+|-+$/g, "").toLowerCase();
291
221
  var fallbackName = (value, fallback) => toHttpApiCliName(value) || fallback;
292
222
  var operationIdParts = (operation) => operation.operationId?.split(".").filter(Boolean) ?? [];
@@ -343,8 +273,8 @@ var schemaType = (schema) => {
343
273
  return type;
344
274
  return schemaType(effectiveSchema(schema));
345
275
  };
346
- var schemaEnum = (schema) => Schema3.decodeUnknownOption(Schema3.Array(Schema3.String))(effectiveSchema(schema).enum).pipe(Option2.getOrElse(() => []));
347
- var jsonFlag = (name) => Flag.String(name).pipe(Flag.mapTryCatch((value) => Schema3.decodeUnknownSync(JsonFromString)(value), () => `--${name} must be valid JSON`));
276
+ var schemaEnum = (schema) => Schema2.decodeUnknownOption(Schema2.Array(Schema2.String))(effectiveSchema(schema).enum).pipe(Option2.getOrElse(() => []));
277
+ var jsonFlag = (name) => Flag.String(name).pipe(Flag.mapTryCatch((value) => Schema2.decodeUnknownSync(JsonFromString)(value), () => `--${name} must be valid JSON`));
348
278
  var primitiveFlag = (name, schema, required) => {
349
279
  const type = schemaType(schema);
350
280
  const choices = schemaEnum(schema);
@@ -452,16 +382,16 @@ var operationInputs = (operation) => {
452
382
  };
453
383
  });
454
384
  };
455
- var HttpApiCliResultStream = Schema3.declare((value) => Stream.isStream(value)).annotate({ identifier: "HttpApiCliResultStream" });
456
- var printHttpApiCliResult = Effect3.fn("HttpApiCli.printResult")(function* (response, operation, client) {
457
- const stream = Schema3.decodeUnknownOption(HttpApiCliResultStream)(response);
385
+ var HttpApiCliResultStream = Schema2.declare((value) => Stream.isStream(value)).annotate({ identifier: "HttpApiCliResultStream" });
386
+ var printHttpApiCliResult = Effect2.fn("HttpApiCli.printResult")(function* (response, operation, client) {
387
+ const stream = Schema2.decodeUnknownOption(HttpApiCliResultStream)(response);
458
388
  if (stream._tag === "Some") {
459
389
  return yield* stream.value.pipe(Stream.mapEffect((event) => client.encodeResult(event, operation)), Stream.runForEach((event) => print(JSON.stringify(event))));
460
390
  }
461
391
  const encoded = yield* client.encodeResult(response, operation);
462
392
  return yield* print(JSON.stringify(encoded, null, 2) ?? "null");
463
393
  });
464
- var callOperation = Effect3.fn("HttpApiCli.callOperation")(function* (operation, inputs, callConfig, client) {
394
+ var callOperation = Effect2.fn("HttpApiCli.callOperation")(function* (operation, inputs, callConfig, client) {
465
395
  const emptyValues = () => ({});
466
396
  const assembled = {
467
397
  body: emptyValues(),
@@ -469,28 +399,28 @@ var callOperation = Effect3.fn("HttpApiCli.callOperation")(function* (operation,
469
399
  params: emptyValues(),
470
400
  query: emptyValues()
471
401
  };
472
- for (const input2 of inputs) {
473
- const parsed = callConfig[input2.configKey];
402
+ for (const input of inputs) {
403
+ const parsed = callConfig[input.configKey];
474
404
  const value = Option2.isOption(parsed) ? Option2.getOrUndefined(parsed) : parsed;
475
405
  if (value !== undefined) {
476
- assembled[input2.location][input2.name] = value;
406
+ assembled[input.location][input.name] = value;
477
407
  }
478
408
  }
479
- const bodyInput = inputs.some((input2) => input2.location === "body" && input2.name === "body") ? assembled.body.body : Object.keys(assembled.body).length > 0 || cliJsonSchema(operation.inputJsonSchema).required?.includes("body") ? assembled.body : undefined;
409
+ const bodyInput = inputs.some((input) => input.location === "body" && input.name === "body") ? assembled.body.body : Object.keys(assembled.body).length > 0 || cliJsonSchema(operation.inputJsonSchema).required?.includes("body") ? assembled.body : undefined;
480
410
  const rawInput = {};
481
- if (inputs.some((input2) => input2.location === "params")) {
411
+ if (inputs.some((input) => input.location === "params")) {
482
412
  rawInput.params = assembled.params;
483
413
  }
484
- if (inputs.some((input2) => input2.location === "headers")) {
414
+ if (inputs.some((input) => input.location === "headers")) {
485
415
  rawInput.headers = assembled.headers;
486
416
  }
487
- if (inputs.some((input2) => input2.location === "query")) {
417
+ if (inputs.some((input) => input.location === "query")) {
488
418
  rawInput.query = assembled.query;
489
419
  }
490
420
  if (bodyInput !== undefined)
491
421
  rawInput.body = bodyInput;
492
- const input = yield* Schema3.decodeUnknownEffect(operation.inputSchema)(rawInput).pipe(Effect3.mapError((error) => new Error(`Invalid input for ${operation.groupName} ${operation.name}: ${error.message}`)));
493
- const response = yield* executeHttpApiOperation({ operation, input }, client);
422
+ const input = yield* Schema2.decodeUnknownEffect(operation.inputSchema)(rawInput).pipe(Effect2.mapError((error) => new Error(`Invalid input for ${operation.groupName} ${operation.name}: ${error.message}`)));
423
+ const response = yield* client.execute({ operation, input });
494
424
  return yield* printHttpApiCliResult(response, operation, client);
495
425
  });
496
426
  var listCommand = (groups) => Command.make("list", {}, () => print([
@@ -499,75 +429,31 @@ var listCommand = (groups) => Command.make("list", {}, () => print([
499
429
  ].join(`
500
430
  `))).pipe(Command.withDescription("List command groups"));
501
431
  var groupListCommand = (group) => Command.make("list", {}, () => listOperations(group.operations)).pipe(Command.withDescription(`List ${group.title} operations`));
502
- var operationCommand = (operation, client) => Effect3.sync(() => {
432
+ var operationCommand = (operation, client) => Effect2.sync(() => {
503
433
  const inputs = operationInputs(operation);
504
434
  const config = Object.fromEntries(inputs.map((input) => [input.configKey, input.param]));
505
- return Command.make(operation.name, config, (callConfig) => Schema3.decodeUnknownEffect(CliParsedConfig)(callConfig).pipe(Effect3.flatMap((parsed) => callOperation(operation, inputs, parsed, client)))).pipe(Command.withDescription(operation.summary || `${operation.method.toUpperCase()} ${operation.path}`), Command.withExamples([
435
+ return Command.make(operation.name, config, (callConfig) => Schema2.decodeUnknownEffect(CliParsedConfig)(callConfig).pipe(Effect2.flatMap((parsed) => callOperation(operation, inputs, parsed, client)))).pipe(Command.withDescription(operation.summary || `${operation.method.toUpperCase()} ${operation.path}`), Command.withExamples([
506
436
  {
507
437
  command: `${operation.groupName} ${operation.name}`,
508
438
  description: `${operation.method.toUpperCase()} ${operation.path}`
509
439
  }
510
440
  ]));
511
441
  });
512
- var groupCommand = (group, client) => Effect3.all(group.operations.map((operation) => operationCommand(operation, client))).pipe(Effect3.map((operationCommands) => Command.make(group.name).pipe(Command.withDescription(group.title), Command.withSubcommands([
442
+ var groupCommand = (group, client) => Effect2.all(group.operations.map((operation) => operationCommand(operation, client))).pipe(Effect2.map((operationCommands) => Command.make(group.name).pipe(Command.withDescription(group.title), Command.withSubcommands([
513
443
  groupListCommand(group),
514
444
  ...operationCommands
515
445
  ]))));
516
- var makeHttpApiCliCommand = Effect3.fn("HttpApiCli.makeCommand")(function* () {
517
- const spec = yield* HttpApiSpec;
518
- const client = yield* ApiClient;
446
+ var makeHttpApiCliCommand = Effect2.fn("HttpApiCli.makeCommand")(function* () {
447
+ const spec = yield* HttpApiAdapter;
448
+ const client = spec;
519
449
  const name = fallbackName(spec.info.title, "api");
520
- const groups = yield* Effect3.try({
450
+ const groups = yield* Effect2.try({
521
451
  try: () => httpApiCliOperationGroups(spec.operations.map(toCliOperation)),
522
452
  catch: (error) => error instanceof Error ? error : new Error(String(error))
523
453
  });
524
- const groupCommands = yield* Effect3.all(groups.map((group) => groupCommand(group, client)));
454
+ const groupCommands = yield* Effect2.all(groups.map((group) => groupCommand(group, client)));
525
455
  return Command.make(name).pipe(Command.withDescription(spec.info.description ?? spec.info.title), Command.withSubcommands([listCommand(groups), ...groupCommands]));
526
456
  });
527
- var cliEnvironmentLayer = (args) => Layer3.mergeAll(FileSystem.layerNoop({}), Path.layer, Stdio.layerTest({ args: Effect3.succeed(Array.from(args)) }), Layer3.succeed(Terminal.Terminal, Terminal.make({
528
- columns: Effect3.sync(() => process.stdout.columns ?? 80),
529
- rows: Effect3.sync(() => process.stdout.rows ?? 24),
530
- readInput: Effect3.die("Terminal input is not supported"),
531
- readLine: Effect3.die("Terminal input is not supported"),
532
- display: (text) => Effect3.sync(() => process.stdout.write(text))
533
- })), Layer3.succeed(ChildProcessSpawner, ChildProcessSpawner.of({
534
- spawn: () => Effect3.die("Child processes are not supported"),
535
- exitCode: () => Effect3.die("Child processes are not supported"),
536
- streamString: () => Stream.die("Child processes are not supported"),
537
- streamLines: () => Stream.die("Child processes are not supported"),
538
- lines: () => Effect3.die("Child processes are not supported"),
539
- string: () => Effect3.die("Child processes are not supported")
540
- })));
541
- var httpApiCliEnvironmentLayer = (args) => cliEnvironmentLayer(args);
542
- var httpApiCli = (args = process.argv.slice(2)) => Effect3.gen(function* () {
543
- const cli = yield* HttpApiCli;
544
- return yield* cli.run(args);
545
- });
546
- var formatHttpApiCliCause = (cause) => {
547
- const errors = Cause.prettyErrors(cause);
548
- if (errors.length === 0)
549
- return Cause.pretty(cause);
550
- return errors.map((error) => error.message ? `${error.name}: ${error.message}` : error.name).join(`
551
- `);
552
- };
553
- var runHttpApiCli = (layer, args = process.argv.slice(2)) => {
554
- Effect3.runPromiseExit(httpApiCli(args).pipe(Effect3.provide(layer), Effect3.provide(httpApiCliEnvironmentLayer(args)))).then(Exit.match({
555
- onSuccess: () => {
556
- return;
557
- },
558
- onFailure: (cause) => {
559
- console.error(formatHttpApiCliCause(cause));
560
- process.exitCode = 1;
561
- }
562
- }));
563
- };
564
457
  export {
565
- HttpApiCli,
566
- formatHttpApiCliCause,
567
- httpApiCli,
568
- httpApiCliEnvironmentLayer,
569
- makeHttpApiCliCommand,
570
- printHttpApiCliResult,
571
- runHttpApiCli,
572
- toHttpApiCliName
458
+ makeHttpApiCli
573
459
  };
@@ -1,31 +1,22 @@
1
- import { Effect, Layer, Schema } from "effect";
1
+ import { Effect, Schema } from "effect";
2
2
  import type { Json } from "effect/Schema";
3
3
  import { Tool, Toolkit } from "effect/ai";
4
- import { ApiClient } from "./httpapi-client.js";
5
- import { HttpApiSpec, type HttpApiOperationEntry } from "./httpapi-helpers.js";
4
+ import { HttpApiAdapter } from "./httpapi-adapter.js";
5
+ import { type HttpApiOperationEntry } from "./httpapi-adapter.js";
6
6
  export type HttpApiToolkitConfig = {
7
7
  readonly toolMetaKey?: string;
8
8
  readonly needsApproval?: (operation: HttpApiOperationEntry) => boolean;
9
9
  readonly strict?: (operation: HttpApiOperationEntry) => boolean;
10
10
  readonly transformResult?: (operation: HttpApiOperationEntry, result: Json) => Json;
11
11
  };
12
- export declare const makeHttpApiToolkit: (config: HttpApiToolkitConfig) => Effect.Effect<{
12
+ export declare const makeHttpApiToolkit: (config?: HttpApiToolkitConfig | undefined) => Effect.Effect<{
13
13
  toolkit: Toolkit.Toolkit<{
14
14
  readonly [x: string]: Tool.Tool<string, {
15
- readonly parameters: Schema.Codec<Partial<import("./httpapi-helpers.js").HttpApiOperationInput>, Json, never, never>;
15
+ readonly parameters: Schema.Codec<Partial<import("./httpapi-adapter.js").HttpApiOperationInput>, Json, never, never>;
16
16
  readonly success: Schema.Codec<Json, Json, never, never>;
17
17
  readonly failure: Schema.String;
18
18
  readonly failureMode: "return";
19
19
  }, never>;
20
20
  }>;
21
- handlers: Layer.Layer<Tool.Handler<string>, never, ApiClient>;
22
- }, never, HttpApiSpec>;
23
- export declare const HttpApiToolkit: (config: HttpApiToolkitConfig) => Effect.Effect<Toolkit.Toolkit<{
24
- readonly [x: string]: Tool.Tool<string, {
25
- readonly parameters: Schema.Codec<Partial<import("./httpapi-helpers.js").HttpApiOperationInput>, Json, never, never>;
26
- readonly success: Schema.Codec<Json, Json, never, never>;
27
- readonly failure: Schema.String;
28
- readonly failureMode: "return";
29
- }, never>;
30
- }>, never, HttpApiSpec>;
31
- export declare const HttpApiToolkitLayer: (config: HttpApiToolkitConfig) => Layer.Layer<Tool.Handler<string>, never, ApiClient | HttpApiSpec>;
21
+ handlers: import("effect/Layer").Layer<Tool.Handler<string>, never, HttpApiAdapter>;
22
+ }, never, HttpApiAdapter>;