@smthrs/std 1.0.0-rc.4 → 1.0.0-rc.6

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 (69) hide show
  1. package/README.md +3 -3
  2. package/dist/cjs/ExaWebSearch.js +1 -1
  3. package/dist/cjs/ExaWebSearch.js.map +1 -1
  4. package/dist/cjs/Fetch.d.ts +1 -1
  5. package/dist/cjs/Fetch.d.ts.map +1 -1
  6. package/dist/cjs/Fetch.js +1 -1
  7. package/dist/cjs/Fetch.js.map +2 -2
  8. package/dist/cjs/HttpPost.d.ts +1 -1
  9. package/dist/cjs/HttpPost.d.ts.map +1 -1
  10. package/dist/cjs/HttpPost.js +1 -1
  11. package/dist/cjs/HttpPost.js.map +2 -2
  12. package/dist/cjs/Lsp.d.ts +1 -1
  13. package/dist/cjs/Manifest.d.ts +8 -8
  14. package/dist/cjs/NodeLanguageServer.js +1 -1
  15. package/dist/cjs/NodeLanguageServer.js.map +1 -1
  16. package/dist/cjs/WebFetch.d.ts.map +1 -1
  17. package/dist/cjs/WebFetch.js +1 -1
  18. package/dist/cjs/WebFetch.js.map +2 -2
  19. package/dist/cjs/internal/Exec.d.ts.map +1 -1
  20. package/dist/cjs/internal/Exec.js +1 -1
  21. package/dist/cjs/internal/Exec.js.map +2 -2
  22. package/dist/cjs/internal/Http.d.ts +1 -1
  23. package/dist/cjs/internal/Http.d.ts.map +1 -1
  24. package/dist/cjs/internal/Http.js +1 -1
  25. package/dist/cjs/internal/Http.js.map +2 -2
  26. package/dist/cjs/internal/HttpNetwork.d.ts +2 -2
  27. package/dist/cjs/internal/HttpNetwork.d.ts.map +1 -1
  28. package/dist/cjs/internal/HttpNetwork.js +3 -3
  29. package/dist/cjs/internal/HttpNetwork.js.map +1 -1
  30. package/dist/esm/ExaWebSearch.js +1 -1
  31. package/dist/esm/ExaWebSearch.js.map +1 -1
  32. package/dist/esm/Fetch.d.ts +1 -1
  33. package/dist/esm/Fetch.d.ts.map +1 -1
  34. package/dist/esm/Fetch.js +1 -1
  35. package/dist/esm/Fetch.js.map +1 -1
  36. package/dist/esm/HttpPost.d.ts +1 -1
  37. package/dist/esm/HttpPost.d.ts.map +1 -1
  38. package/dist/esm/HttpPost.js +1 -1
  39. package/dist/esm/HttpPost.js.map +1 -1
  40. package/dist/esm/Lsp.d.ts +1 -1
  41. package/dist/esm/Manifest.d.ts +8 -8
  42. package/dist/esm/NodeLanguageServer.js +1 -1
  43. package/dist/esm/NodeLanguageServer.js.map +1 -1
  44. package/dist/esm/WebFetch.d.ts.map +1 -1
  45. package/dist/esm/WebFetch.js +1 -1
  46. package/dist/esm/WebFetch.js.map +1 -1
  47. package/dist/esm/internal/Exec.d.ts.map +1 -1
  48. package/dist/esm/internal/Exec.js +1 -1
  49. package/dist/esm/internal/Exec.js.map +1 -1
  50. package/dist/esm/internal/Http.d.ts +1 -1
  51. package/dist/esm/internal/Http.d.ts.map +1 -1
  52. package/dist/esm/internal/Http.js +1 -1
  53. package/dist/esm/internal/Http.js.map +1 -1
  54. package/dist/esm/internal/HttpNetwork.d.ts +2 -2
  55. package/dist/esm/internal/HttpNetwork.d.ts.map +1 -1
  56. package/dist/esm/internal/HttpNetwork.js +3 -3
  57. package/dist/esm/internal/HttpNetwork.js.map +1 -1
  58. package/docs/guides/run-a-shell-command.md +8 -0
  59. package/docs/installation.md +1 -1
  60. package/docs/troubleshooting.md +5 -0
  61. package/package.json +10 -10
  62. package/src/ExaWebSearch.ts +1 -1
  63. package/src/Fetch.ts +1 -1
  64. package/src/HttpPost.ts +1 -1
  65. package/src/NodeLanguageServer.ts +1 -1
  66. package/src/WebFetch.ts +1 -1
  67. package/src/internal/Exec.ts +1 -1
  68. package/src/internal/Http.ts +1 -1
  69. package/src/internal/HttpNetwork.ts +3 -3
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/WebFetch.ts"],
4
- "sourcesContent": ["/**\n * The `webfetch` flow: an HTTP GET rendered as text, Markdown, or HTML.\n *\n * The handler fetches through the permission-checked `HttpClient`, follows at\n * most ten redirects, refuses a body over 5 MiB, and returns the final URL,\n * status, and content type beside the rendered body. The rendered body keeps\n * its first 60,000 bytes and reports any cut with `truncated` and `notice`.\n *\n * @since 1.0.0\n */\n\nimport type { GrantStore } from \"@smthrs/kernel/GrantStore\"\nimport * as HttpClient from \"@smthrs/kernel/HttpClient\"\nimport * as Effect from \"effect/Effect\"\nimport * as Schema from \"effect/Schema\"\nimport * as HttpClientRequest from \"effect/unstable/http/HttpClientRequest\"\nimport { capability, envelope } from \"./internal/Declaration.ts\"\nimport { toMarkdown, toText } from \"./internal/Html.ts\"\nimport { capOutput, header, MAX_RESPONSE_BYTES, readBounded, Timeout, withDeadline } from \"./internal/Http.ts\"\nimport { guarded, refusal } from \"./internal/HttpNetwork.ts\"\nimport { parseHttpUrl } from \"./internal/Url.ts\"\nimport * as StdError from \"./StdError.ts\"\n\nconst maxRedirects = 10\n/**\n * The registry name of the `webfetch` flow.\n *\n * @category identifiers\n * @since 1.0.0\n */\nexport const name = \"webfetch\"\n/**\n * The one-line description the model sees for the `webfetch` flow.\n *\n * @category descriptions\n * @since 1.0.0\n */\nexport const description = \"Fetch an HTTP URL and render its content as text, Markdown, or HTML.\"\n/**\n * What the `webfetch` flow accepts.\n *\n * @category schemas\n * @since 1.0.0\n */\nexport const Input = Schema.Struct({\n url: Schema.String.annotate({ description: \"Absolute http or https URL to retrieve without user information\" }),\n format: Schema.optional(Schema.Literals([\"text\", \"markdown\", \"html\"])).annotate({\n description: \"Response rendering format; defaults to markdown\"\n }),\n timeout: Schema.optional(Timeout).annotate({\n description: \"Total timeout across requests, redirects, and response body in seconds, capped at 120\"\n })\n})\n/**\n * Decoded input accepted by the `webfetch` flow.\n *\n * @category models\n * @since 1.0.0\n */\nexport type Input = typeof Input.Type\n/**\n * What the `webfetch` flow returns.\n *\n * @category schemas\n * @since 1.0.0\n */\nexport const Output = Schema.Struct({\n url: Schema.String.annotate({ description: \"Final URL after redirects\" }),\n status: Schema.Int.annotate({ description: \"HTTP status code, including error statuses\" }),\n contentType: Schema.String.annotate({ description: \"Response Content-Type header, or an empty string when absent\" }),\n content: Schema.String.annotate({ description: \"Response body rendered in the requested format\" }),\n truncated: Schema.Boolean.annotate({ description: \"Whether the rendered body exceeded the display budget\" }),\n notice: Schema.optional(Schema.String.annotate({ description: \"Truncation disclosure\" }))\n})\n/**\n * Decoded output returned by the `webfetch` flow.\n *\n * @category models\n * @since 1.0.0\n */\nexport type Output = typeof Output.Type\n/**\n * The declared effect envelope of the `webfetch` flow, before any input is known.\n *\n * @category effects\n * @since 1.0.0\n */\nexport const effects = envelope({ tier: \"sealed\", mode: \"expected\", reads: [], writes: [] })\n/**\n * Narrows {@link effects} to what this particular input actually touches.\n *\n * @category effects\n * @since 1.0.0\n */\nexport const effectsFor = (_input: typeof Input.Type) => effects\n/**\n * The authority the `webfetch` flow requires.\n *\n * @category capabilities\n * @since 1.0.0\n */\nexport const capabilities = [capability(\"net:get\", \"*\")]\n/**\n * The `webfetch` flow declaration: schemas, capabilities, and effects, with the\n * implementation attached separately.\n *\n * @category flows\n * @since 1.0.0\n */\nexport const flow = { name, description, input: Input, output: Output, capabilities, effects } as const\n\nconst error = (code: StdError.Code, message: string, path?: string): StdError.StdError =>\n new StdError.StdError({ code, message, ...(path === undefined ? {} : { path }) })\n/**\n * Runs the `webfetch` flow: fetches one HTTP URL and renders it as text.\n *\n * @category handlers\n * @since 1.0.0\n */\nexport const run = Effect.fn(\"WebFetch.run\")(function*(\n input: typeof Input.Type\n): Effect.fn.Return<typeof Output.Type, StdError.StdError, HttpClient.HttpClient | GrantStore> {\n let url = parseHttpUrl(input.url)\n if (url === undefined) {\n return yield* Effect.fail(\n error(\"invalid_input\", \"URL must use http or https without user information\", input.url)\n )\n }\n const client = guarded(yield* HttpClient.HttpClient, false)\n let headers: Readonly<Record<string, string>> = {\n accept: input.format === \"html\" ? \"text/html, text/plain;q=0.8\" : \"text/markdown, text/plain, text/html;q=0.8\"\n }\n for (let redirect = 0; redirect <= maxRedirects; redirect++) {\n const response = yield* client.execute(\n HttpClientRequest.setHeaders(HttpClientRequest.get(url.toString()), headers)\n ).pipe(\n Effect.mapError((cause) => refusal(cause) ?? error(\"request_failed\", `Web fetch request failed: ${url}`))\n )\n const location = header(response.headers, \"location\")\n if (response.status >= 300 && response.status < 400 && location !== undefined) {\n const next = parseHttpUrl(location, url)\n if (next === undefined) {\n return yield* Effect.fail(\n error(\"invalid_input\", \"Redirect target must use http or https without user information\", location)\n )\n }\n if (next.origin !== url.origin) {\n headers = Object.fromEntries(\n Object.entries(headers).filter(([key]) =>\n key.toLowerCase() !== \"authorization\" && key.toLowerCase() !== \"cookie\"\n )\n )\n }\n url = next\n continue\n }\n const contentType = header(response.headers, \"content-type\") ?? \"\"\n const normalizedContentType = contentType.toLowerCase()\n if (\n !normalizedContentType.startsWith(\"text/\")\n && !normalizedContentType.includes(\"json\")\n && !normalizedContentType.includes(\"xml\")\n ) {\n return yield* Effect.fail(\n error(\"unsupported_content_type\", `Unsupported content type: ${contentType || \"unknown\"}`)\n )\n }\n const length = Number(header(response.headers, \"content-length\"))\n if (Number.isFinite(length) && length > MAX_RESPONSE_BYTES) {\n return yield* Effect.fail(error(\"response_too_large\", \"Response exceeds the 5 MiB limit\"))\n }\n const body = yield* readBounded(response.stream, url.toString()).pipe(\n Effect.mapError((cause) =>\n cause instanceof StdError.StdError\n ? cause\n : error(\"request_failed\", \"Web fetch response could not be read\")\n )\n )\n const raw = new TextDecoder().decode(body)\n const format = input.format ?? \"markdown\"\n const { text: content, ...disclosure } = capOutput(\n format === \"html\" || !normalizedContentType.includes(\"html\")\n ? raw\n : format === \"text\"\n ? toText(raw)\n : toMarkdown(raw)\n )\n return { url: url.toString(), status: response.status, contentType, content, ...disclosure }\n }\n return yield* Effect.fail(error(\"request_failed\", \"Web fetch exceeded the redirect limit\"))\n}, (effect, input) =>\n // Keep the shared deadline outside the redirect loop and error mapping.\n withDeadline(effect, input.url, input.timeout, (seconds) =>\n error(\"timeout\", `Web fetch timed out after ${seconds} seconds`)))\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\n * The `webfetch` flow: an HTTP GET rendered as text, Markdown, or HTML.\n *\n * The handler fetches through the permission-checked `HttpClient`, follows at\n * most ten redirects, refuses a body over 5 MiB, and returns the final URL,\n * status, and content type beside the rendered body. The rendered body keeps\n * its first 60,000 bytes and reports any cut with `truncated` and `notice`.\n *\n * @since 1.0.0\n */\n\nimport type { GrantStore } from \"@smthrs/kernel/GrantStore\"\nimport * as HttpClient from \"@smthrs/kernel/HttpClient\"\nimport * as Effect from \"effect/Effect\"\nimport * as HttpClientRequest from \"effect/http/HttpClientRequest\"\nimport * as Schema from \"effect/Schema\"\nimport { capability, envelope } from \"./internal/Declaration.ts\"\nimport { toMarkdown, toText } from \"./internal/Html.ts\"\nimport { capOutput, header, MAX_RESPONSE_BYTES, readBounded, Timeout, withDeadline } from \"./internal/Http.ts\"\nimport { guarded, refusal } from \"./internal/HttpNetwork.ts\"\nimport { parseHttpUrl } from \"./internal/Url.ts\"\nimport * as StdError from \"./StdError.ts\"\n\nconst maxRedirects = 10\n/**\n * The registry name of the `webfetch` flow.\n *\n * @category identifiers\n * @since 1.0.0\n */\nexport const name = \"webfetch\"\n/**\n * The one-line description the model sees for the `webfetch` flow.\n *\n * @category descriptions\n * @since 1.0.0\n */\nexport const description = \"Fetch an HTTP URL and render its content as text, Markdown, or HTML.\"\n/**\n * What the `webfetch` flow accepts.\n *\n * @category schemas\n * @since 1.0.0\n */\nexport const Input = Schema.Struct({\n url: Schema.String.annotate({ description: \"Absolute http or https URL to retrieve without user information\" }),\n format: Schema.optional(Schema.Literals([\"text\", \"markdown\", \"html\"])).annotate({\n description: \"Response rendering format; defaults to markdown\"\n }),\n timeout: Schema.optional(Timeout).annotate({\n description: \"Total timeout across requests, redirects, and response body in seconds, capped at 120\"\n })\n})\n/**\n * Decoded input accepted by the `webfetch` flow.\n *\n * @category models\n * @since 1.0.0\n */\nexport type Input = typeof Input.Type\n/**\n * What the `webfetch` flow returns.\n *\n * @category schemas\n * @since 1.0.0\n */\nexport const Output = Schema.Struct({\n url: Schema.String.annotate({ description: \"Final URL after redirects\" }),\n status: Schema.Int.annotate({ description: \"HTTP status code, including error statuses\" }),\n contentType: Schema.String.annotate({ description: \"Response Content-Type header, or an empty string when absent\" }),\n content: Schema.String.annotate({ description: \"Response body rendered in the requested format\" }),\n truncated: Schema.Boolean.annotate({ description: \"Whether the rendered body exceeded the display budget\" }),\n notice: Schema.optional(Schema.String.annotate({ description: \"Truncation disclosure\" }))\n})\n/**\n * Decoded output returned by the `webfetch` flow.\n *\n * @category models\n * @since 1.0.0\n */\nexport type Output = typeof Output.Type\n/**\n * The declared effect envelope of the `webfetch` flow, before any input is known.\n *\n * @category effects\n * @since 1.0.0\n */\nexport const effects = envelope({ tier: \"sealed\", mode: \"expected\", reads: [], writes: [] })\n/**\n * Narrows {@link effects} to what this particular input actually touches.\n *\n * @category effects\n * @since 1.0.0\n */\nexport const effectsFor = (_input: typeof Input.Type) => effects\n/**\n * The authority the `webfetch` flow requires.\n *\n * @category capabilities\n * @since 1.0.0\n */\nexport const capabilities = [capability(\"net:get\", \"*\")]\n/**\n * The `webfetch` flow declaration: schemas, capabilities, and effects, with the\n * implementation attached separately.\n *\n * @category flows\n * @since 1.0.0\n */\nexport const flow = { name, description, input: Input, output: Output, capabilities, effects } as const\n\nconst error = (code: StdError.Code, message: string, path?: string): StdError.StdError =>\n new StdError.StdError({ code, message, ...(path === undefined ? {} : { path }) })\n/**\n * Runs the `webfetch` flow: fetches one HTTP URL and renders it as text.\n *\n * @category handlers\n * @since 1.0.0\n */\nexport const run = Effect.fn(\"WebFetch.run\")(function*(\n input: typeof Input.Type\n): Effect.fn.Return<typeof Output.Type, StdError.StdError, HttpClient.HttpClient | GrantStore> {\n let url = parseHttpUrl(input.url)\n if (url === undefined) {\n return yield* Effect.fail(\n error(\"invalid_input\", \"URL must use http or https without user information\", input.url)\n )\n }\n const client = guarded(yield* HttpClient.HttpClient, false)\n let headers: Readonly<Record<string, string>> = {\n accept: input.format === \"html\" ? \"text/html, text/plain;q=0.8\" : \"text/markdown, text/plain, text/html;q=0.8\"\n }\n for (let redirect = 0; redirect <= maxRedirects; redirect++) {\n const response = yield* client.execute(\n HttpClientRequest.setHeaders(HttpClientRequest.get(url.toString()), headers)\n ).pipe(\n Effect.mapError((cause) => refusal(cause) ?? error(\"request_failed\", `Web fetch request failed: ${url}`))\n )\n const location = header(response.headers, \"location\")\n if (response.status >= 300 && response.status < 400 && location !== undefined) {\n const next = parseHttpUrl(location, url)\n if (next === undefined) {\n return yield* Effect.fail(\n error(\"invalid_input\", \"Redirect target must use http or https without user information\", location)\n )\n }\n if (next.origin !== url.origin) {\n headers = Object.fromEntries(\n Object.entries(headers).filter(([key]) =>\n key.toLowerCase() !== \"authorization\" && key.toLowerCase() !== \"cookie\"\n )\n )\n }\n url = next\n continue\n }\n const contentType = header(response.headers, \"content-type\") ?? \"\"\n const normalizedContentType = contentType.toLowerCase()\n if (\n !normalizedContentType.startsWith(\"text/\")\n && !normalizedContentType.includes(\"json\")\n && !normalizedContentType.includes(\"xml\")\n ) {\n return yield* Effect.fail(\n error(\"unsupported_content_type\", `Unsupported content type: ${contentType || \"unknown\"}`)\n )\n }\n const length = Number(header(response.headers, \"content-length\"))\n if (Number.isFinite(length) && length > MAX_RESPONSE_BYTES) {\n return yield* Effect.fail(error(\"response_too_large\", \"Response exceeds the 5 MiB limit\"))\n }\n const body = yield* readBounded(response.stream, url.toString()).pipe(\n Effect.mapError((cause) =>\n cause instanceof StdError.StdError\n ? cause\n : error(\"request_failed\", \"Web fetch response could not be read\")\n )\n )\n const raw = new TextDecoder().decode(body)\n const format = input.format ?? \"markdown\"\n const { text: content, ...disclosure } = capOutput(\n format === \"html\" || !normalizedContentType.includes(\"html\")\n ? raw\n : format === \"text\"\n ? toText(raw)\n : toMarkdown(raw)\n )\n return { url: url.toString(), status: response.status, contentType, content, ...disclosure }\n }\n return yield* Effect.fail(error(\"request_failed\", \"Web fetch exceeded the redirect limit\"))\n}, (effect, input) =>\n // Keep the shared deadline outside the redirect loop and error mapping.\n withDeadline(effect, input.url, input.timeout, (seconds) =>\n error(\"timeout\", `Web fetch timed out after ${seconds} seconds`)))\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -1 +1 @@
1
- {"version":3,"file":"Exec.d.ts","sourceRoot":"","sources":["../../../src/internal/Exec.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAGH,OAAO,KAAK,mBAAmB,MAAM,oCAAoC,CAAA;AACzE,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AACvC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AAGvC,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAA;AAE1C;;;;;;GAMG;AACH,eAAO,MAAM,aAAa,0EAAkE,CAAA;AAE5F;;;;;GAKG;AACH,MAAM,MAAM,aAAa,GAAG,OAAO,aAAa,CAAC,IAAI,CAAA;;;;IAenD,uDAAuD;;;AAbzD;;;;;;;;;GASG;AACH,qBAAa,SAAU,SAAQ,cAK7B;CAAG;AAEL;;;;;GAKG;AACH,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,oFAAoF;IACpF,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAA;IACnC,oFAAoF;IACpF,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAA;CACpC;AAED;;;;;GAKG;AACH,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IACjC,QAAQ,CAAC,GAAG,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GAAG,SAAS,CAAA;IAC3D,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IACvC;;;;;OAKG;IACH,QAAQ,CAAC,IAAI,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,GAAG,SAAS,CAAA;IACjD;;;;;OAKG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IACnC;;;;;;;OAOG;IACH,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAC7C,6EAA6E;IAC7E,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,SAAS,CAAA;CAClD;AAiJD;;;;;;;;;GASG;AACH,eAAO,MAAM,IAAI,GACf,SAAS,MAAM,EACf,UAAS,WAAgB,KACxB,MAAM,CAAC,MAAM,CAAC,UAAU,EAAE,SAAS,EAAE,mBAAmB,CAAC,mBAAmB,CAazE,CAAA;AAEN;;;;;;;;;;GAUG;AACH,eAAO,MAAM,cAAc,GAAI,OAAO,SAAS,KAAG,QAAQ,CAAC,IACF,CAAA;AAEzD;;;;;;;;;GASG;AACH,eAAO,MAAM,UAAU,GAAI,SAAS,MAAM,EAAE,OAAO,SAAS,KAAG,QAAQ,CAAC,QAOpE,CAAA"}
1
+ {"version":3,"file":"Exec.d.ts","sourceRoot":"","sources":["../../../src/internal/Exec.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAGH,OAAO,KAAK,mBAAmB,MAAM,oCAAoC,CAAA;AACzE,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AAEvC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AAEvC,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAA;AAE1C;;;;;;GAMG;AACH,eAAO,MAAM,aAAa,0EAAkE,CAAA;AAE5F;;;;;GAKG;AACH,MAAM,MAAM,aAAa,GAAG,OAAO,aAAa,CAAC,IAAI,CAAA;;;;IAenD,uDAAuD;;;AAbzD;;;;;;;;;GASG;AACH,qBAAa,SAAU,SAAQ,cAK7B;CAAG;AAEL;;;;;GAKG;AACH,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,oFAAoF;IACpF,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAA;IACnC,oFAAoF;IACpF,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAA;CACpC;AAED;;;;;GAKG;AACH,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IACjC,QAAQ,CAAC,GAAG,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GAAG,SAAS,CAAA;IAC3D,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IACvC;;;;;OAKG;IACH,QAAQ,CAAC,IAAI,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,GAAG,SAAS,CAAA;IACjD;;;;;OAKG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IACnC;;;;;;;OAOG;IACH,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAC7C,6EAA6E;IAC7E,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,SAAS,CAAA;CAClD;AAiJD;;;;;;;;;GASG;AACH,eAAO,MAAM,IAAI,GACf,SAAS,MAAM,EACf,UAAS,WAAgB,KACxB,MAAM,CAAC,MAAM,CAAC,UAAU,EAAE,SAAS,EAAE,mBAAmB,CAAC,mBAAmB,CAazE,CAAA;AAEN;;;;;;;;;;GAUG;AACH,eAAO,MAAM,cAAc,GAAI,OAAO,SAAS,KAAG,QAAQ,CAAC,IACF,CAAA;AAEzD;;;;;;;;;GASG;AACH,eAAO,MAAM,UAAU,GAAI,SAAS,MAAM,EAAE,OAAO,SAAS,KAAG,QAAQ,CAAC,QAOpE,CAAA"}
@@ -38,9 +38,9 @@ module.exports = __toCommonJS(Exec_exports);
38
38
  var ChildProcessEnvironment = __toESM(require("@smthrs/kernel/ChildProcessEnvironment"), 1);
39
39
  var ChildProcessSpawner = __toESM(require("@smthrs/kernel/ChildProcessSpawner"), 1);
40
40
  var Effect = __toESM(require("effect/Effect"), 1);
41
+ var ChildProcess = __toESM(require("effect/process/ChildProcess"), 1);
41
42
  var Schema = __toESM(require("effect/Schema"), 1);
42
43
  var Stream = __toESM(require("effect/Stream"), 1);
43
- var ChildProcess = __toESM(require("effect/unstable/process/ChildProcess"), 1);
44
44
  var StdError = __toESM(require("../StdError.js"), 1);
45
45
  const ExecErrorCode = Schema.Literals(["timeout", "spawn_error", "capture_overflow"]);
46
46
  class ExecError extends Schema.TaggedError()("@smthrs/std/ExecError", {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/internal/Exec.ts"],
4
- "sourcesContent": ["/**\n * Buffered shell execution over the permission-aware process spawner.\n *\n * `@smthrs/kernel` used to expose a `Shell` service whose `exec` returned a\n * buffered `{ stdout, stderr, exitCode }`. The kernel replaced it with\n * `ChildProcessSpawner`, Effect's own process boundary, which streams and has\n * no buffered form. This module is the buffered form the shell flows still\n * want, expressed in terms of the spawner so the `proc:spawn` capability check\n * and the command-line resource stay exactly where the kernel put them.\n *\n * Commands run through the platform shell (`shell: true`), matching the old\n * service: the flows take a command *line*, not an argv.\n *\n * @since 1.0.0\n */\n\nimport * as ChildProcessEnvironment from \"@smthrs/kernel/ChildProcessEnvironment\"\nimport * as ChildProcessSpawner from \"@smthrs/kernel/ChildProcessSpawner\"\nimport * as Effect from \"effect/Effect\"\nimport * as Schema from \"effect/Schema\"\nimport * as Stream from \"effect/Stream\"\nimport * as ChildProcess from \"effect/unstable/process/ChildProcess\"\nimport * as StdError from \"../StdError.ts\"\n\n/**\n * Failure codes a buffered execution can report, matching the codes the\n * removed kernel `Shell` used so handler-level mapping is unchanged.\n *\n * @category models\n * @since 1.0.0\n */\nexport const ExecErrorCode = Schema.Literals([\"timeout\", \"spawn_error\", \"capture_overflow\"])\n\n/**\n * Failure codes a buffered execution can report.\n *\n * @category models\n * @since 1.0.0\n */\nexport type ExecErrorCode = typeof ExecErrorCode.Type\n\n/**\n * A command that never produced an exit code.\n *\n * A non-zero exit is a successful {@link ExecResult}, not a failure; this\n * error is reserved for a command that could not start or was cut off by its\n * timeout, or whose captured output exceeded a refusing capture bound.\n *\n * @category errors\n * @since 1.0.0\n */\nexport class ExecError extends Schema.TaggedError<ExecError>()(\"@smthrs/std/ExecError\", {\n code: ExecErrorCode,\n message: Schema.String,\n /** The limit a `timeout` ran past, in milliseconds. */\n limitMillis: Schema.optional(Schema.Number)\n}) {}\n\n/**\n * The buffered result of one command.\n *\n * @category models\n * @since 1.0.0\n */\nexport interface ExecResult {\n readonly stdout: string\n readonly stderr: string\n readonly exitCode: number\n /** UTF-8 bytes dropped from the head of stdout to stay inside the capture bound. */\n readonly stdoutDroppedBytes: number\n /** UTF-8 bytes dropped from the head of stderr to stay inside the capture bound. */\n readonly stderrDroppedBytes: number\n}\n\n/**\n * Options accepted by {@link exec}.\n *\n * @category models\n * @since 1.0.0\n */\nexport interface ExecOptions {\n readonly cwd?: string | undefined\n readonly env?: Readonly<Record<string, string>> | undefined\n readonly timeoutMs?: number | undefined\n /**\n * The program's arguments. Present means an argv, absent means a command\n * line for the platform shell. An argv is how a payload reaches a program\n * without being quoted into a string: nothing between here and `execve`\n * re-parses it.\n */\n readonly args?: ReadonlyArray<string> | undefined\n /**\n * Text written to the program's standard input, as data. A script delivered\n * this way is never quoted, escaped, or heredoc-terminated, which is the\n * whole point: quoting corruption cost the measured SWE-bench program twelve\n * probe failures and one instance's most expensive frame.\n */\n readonly stdin?: string | undefined\n /**\n * Bytes retained per captured stream. A stream that prints more keeps its\n * tail and reports what it dropped, so a command printing gigabytes costs a\n * bounded amount of memory rather than the whole of what it printed.\n *\n * Absent means unbounded, which is what a caller wants when it needs every\n * byte a tool produced (`rg --files`, `git worktree list`).\n */\n readonly maxCaptureBytes?: number | undefined\n /** Defaults to `tail`; `refuse` fails if either stream exceeds the bound. */\n readonly overflow?: \"tail\" | \"refuse\" | undefined\n}\n\n/** One captured stream: the text kept, and the bytes dropped to keep it bounded. */\ninterface Capture {\n readonly text: string\n readonly droppedBytes: number\n}\n\ninterface Tail {\n chunks: Array<Uint8Array>\n bytes: number\n dropped: number\n}\n\nconst decoder = new TextDecoder(\"utf-8\")\n\n/**\n * Joins the retained chunks and decodes them, skipping the partial code point a\n * dropped head can leave behind.\n *\n * A UTF-8 continuation byte is `10xxxxxx`, and a code point is at most four\n * bytes, so at most three leading continuation bytes can precede the first\n * whole character. Skipping them is counted as dropped rather than decoded to a\n * replacement character the process never printed.\n */\nconst decodeTail = (state: Tail): Capture => {\n const bytes = new Uint8Array(state.bytes)\n let offset = 0\n for (const chunk of state.chunks) {\n bytes.set(chunk, offset)\n offset += chunk.byteLength\n }\n if (state.dropped === 0) return { text: decoder.decode(bytes), droppedBytes: 0 }\n let start = 0\n while (start < bytes.byteLength && start < 3 && (bytes[start]! & 0b1100_0000) === 0b1000_0000) start++\n return { text: decoder.decode(bytes.subarray(start)), droppedBytes: state.dropped + start }\n}\n\nconst boundedTail = <E>(\n stream: Stream.Stream<Uint8Array, E>,\n maxBytes: number,\n overflow: \"tail\" | \"refuse\" | undefined\n): Effect.Effect<Capture, E> =>\n Stream.runFold(\n stream,\n (): Tail => ({ chunks: [], bytes: 0, dropped: 0 }),\n (state, chunk) => {\n if (chunk.byteLength === 0) return state\n state.chunks.push(chunk)\n state.bytes += chunk.byteLength\n while (state.bytes > maxBytes && state.chunks.length > 0) {\n const excess = state.bytes - maxBytes\n const first = state.chunks[0]!\n if (first.byteLength <= excess) {\n state.chunks.shift()\n state.bytes -= first.byteLength\n state.dropped += first.byteLength\n } else {\n state.chunks[0] = first.subarray(excess)\n state.bytes -= excess\n state.dropped += excess\n }\n }\n return state\n }\n ).pipe(Effect.map((state) =>\n overflow === \"refuse\" && state.dropped > 0\n ? { text: \"\", droppedBytes: state.dropped }\n : decodeTail(state)\n ))\n\nconst capture = <E>(\n stream: Stream.Stream<Uint8Array, E>,\n maxBytes: number | undefined,\n overflow: \"tail\" | \"refuse\" | undefined\n): Effect.Effect<Capture, E> =>\n maxBytes === undefined\n ? Effect.map(Stream.mkString(Stream.decodeText(stream)), (text) => ({ text, droppedBytes: 0 }))\n : boundedTail(stream, maxBytes, overflow)\n\nconst unbounded = (\n command: string,\n options: ExecOptions\n): Effect.Effect<ExecResult, ExecError, ChildProcessSpawner.ChildProcessSpawner> =>\n Effect.gen(function*() {\n const spawner = yield* ChildProcessSpawner.ChildProcessSpawner\n const settings: ChildProcess.CommandOptions = {\n ...(options.args === undefined ? { shell: true } : {}),\n ...(options.cwd === undefined ? {} : { cwd: options.cwd }),\n env: ChildProcessEnvironment.make(process.env, options.env),\n extendEnv: false,\n ...(options.stdin === undefined\n ? {}\n : { stdin: Stream.make(new TextEncoder().encode(options.stdin)) })\n }\n const handle = yield* spawner.spawn(\n options.args === undefined\n ? ChildProcess.make(command, settings)\n : ChildProcess.make(command, [...options.args], settings)\n )\n // stdout, stderr, and the exit code have to be consumed concurrently: a\n // command that fills a pipe blocks until the pipe is drained, so waiting\n // for exit first would deadlock on any output larger than the buffer.\n const [stdout, stderr, exitCode] = yield* Effect.all(\n [\n capture(handle.stdout, options.maxCaptureBytes, options.overflow),\n capture(handle.stderr, options.maxCaptureBytes, options.overflow),\n handle.exitCode\n ],\n { concurrency: \"unbounded\" }\n )\n if (options.overflow === \"refuse\") {\n const overflowed = [\n stdout.droppedBytes > 0 ? \"stdout\" : undefined,\n stderr.droppedBytes > 0 ? \"stderr\" : undefined\n ]\n .filter((stream): stream is string => stream !== undefined)\n if (overflowed.length > 0) {\n return yield* Effect.fail(\n new ExecError({\n code: \"capture_overflow\",\n message: `${command} ${\n overflowed.join(\" and \")\n } exceeded the ${options.maxCaptureBytes}-byte capture cap; refusing partial output`\n })\n )\n }\n }\n return {\n stdout: stdout.text,\n stderr: stderr.text,\n exitCode,\n stdoutDroppedBytes: stdout.droppedBytes,\n stderrDroppedBytes: stderr.droppedBytes\n }\n }).pipe(\n Effect.scoped,\n Effect.mapError((error) =>\n error instanceof ExecError ? error : new ExecError({\n code: \"spawn_error\",\n message: `exec: ${command}: ${error.message}`\n })\n )\n )\n\n/**\n * Runs a command line through the platform shell and buffers its output.\n *\n * Cancellation is scope closure: the spawn is scoped, so an interrupted fiber\n * \u2014 including the one a `timeoutMs` interrupts \u2014 terminates the process rather\n * than leaking it.\n *\n * @category execution\n * @since 1.0.0\n */\nexport const exec = (\n command: string,\n options: ExecOptions = {}\n): Effect.Effect<ExecResult, ExecError, ChildProcessSpawner.ChildProcessSpawner> =>\n options.timeoutMs === undefined\n ? unbounded(command, options)\n : Effect.timeoutOrElse(unbounded(command, options), {\n duration: options.timeoutMs,\n orElse: () =>\n Effect.fail(\n new ExecError({\n code: \"timeout\",\n message: `exec: \\`${command}\\` exceeded ${options.timeoutMs}ms`,\n limitMillis: options.timeoutMs\n })\n )\n })\n\n/**\n * The model-facing failure code a command that never produced an exit code\n * carries.\n *\n * A timeout keeps its own code, because \"the command never finished\" and \"the\n * command never started\" are different things to a caller deciding whether to\n * retry. Every other way of producing no exit code is a host failure.\n *\n * @category errors\n * @since 1.0.0\n */\nexport const toStdErrorCode = (error: ExecError): StdError.Code =>\n error.code === \"timeout\" ? \"timeout\" : \"command_failed\"\n\n/**\n * The model-facing failure one execution error becomes.\n *\n * A timeout names the command, which is what the caller asked for and all a\n * timeout has to say. Any other failure carries the message the execution\n * produced, which already names the command.\n *\n * @category errors\n * @since 1.0.0\n */\nexport const toStdError = (command: string, error: ExecError): StdError.StdError =>\n new StdError.StdError({\n code: toStdErrorCode(error),\n message: error.code === \"timeout\"\n ? `Command timed out: ${command}`\n : `Command failed to start: ${error.message}`,\n ...(error.limitMillis === undefined ? {} : { limitMillis: error.limitMillis })\n })\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\n * Buffered shell execution over the permission-aware process spawner.\n *\n * `@smthrs/kernel` used to expose a `Shell` service whose `exec` returned a\n * buffered `{ stdout, stderr, exitCode }`. The kernel replaced it with\n * `ChildProcessSpawner`, Effect's own process boundary, which streams and has\n * no buffered form. This module is the buffered form the shell flows still\n * want, expressed in terms of the spawner so the `proc:spawn` capability check\n * and the command-line resource stay exactly where the kernel put them.\n *\n * Commands run through the platform shell (`shell: true`), matching the old\n * service: the flows take a command *line*, not an argv.\n *\n * @since 1.0.0\n */\n\nimport * as ChildProcessEnvironment from \"@smthrs/kernel/ChildProcessEnvironment\"\nimport * as ChildProcessSpawner from \"@smthrs/kernel/ChildProcessSpawner\"\nimport * as Effect from \"effect/Effect\"\nimport * as ChildProcess from \"effect/process/ChildProcess\"\nimport * as Schema from \"effect/Schema\"\nimport * as Stream from \"effect/Stream\"\nimport * as StdError from \"../StdError.ts\"\n\n/**\n * Failure codes a buffered execution can report, matching the codes the\n * removed kernel `Shell` used so handler-level mapping is unchanged.\n *\n * @category models\n * @since 1.0.0\n */\nexport const ExecErrorCode = Schema.Literals([\"timeout\", \"spawn_error\", \"capture_overflow\"])\n\n/**\n * Failure codes a buffered execution can report.\n *\n * @category models\n * @since 1.0.0\n */\nexport type ExecErrorCode = typeof ExecErrorCode.Type\n\n/**\n * A command that never produced an exit code.\n *\n * A non-zero exit is a successful {@link ExecResult}, not a failure; this\n * error is reserved for a command that could not start or was cut off by its\n * timeout, or whose captured output exceeded a refusing capture bound.\n *\n * @category errors\n * @since 1.0.0\n */\nexport class ExecError extends Schema.TaggedError<ExecError>()(\"@smthrs/std/ExecError\", {\n code: ExecErrorCode,\n message: Schema.String,\n /** The limit a `timeout` ran past, in milliseconds. */\n limitMillis: Schema.optional(Schema.Number)\n}) {}\n\n/**\n * The buffered result of one command.\n *\n * @category models\n * @since 1.0.0\n */\nexport interface ExecResult {\n readonly stdout: string\n readonly stderr: string\n readonly exitCode: number\n /** UTF-8 bytes dropped from the head of stdout to stay inside the capture bound. */\n readonly stdoutDroppedBytes: number\n /** UTF-8 bytes dropped from the head of stderr to stay inside the capture bound. */\n readonly stderrDroppedBytes: number\n}\n\n/**\n * Options accepted by {@link exec}.\n *\n * @category models\n * @since 1.0.0\n */\nexport interface ExecOptions {\n readonly cwd?: string | undefined\n readonly env?: Readonly<Record<string, string>> | undefined\n readonly timeoutMs?: number | undefined\n /**\n * The program's arguments. Present means an argv, absent means a command\n * line for the platform shell. An argv is how a payload reaches a program\n * without being quoted into a string: nothing between here and `execve`\n * re-parses it.\n */\n readonly args?: ReadonlyArray<string> | undefined\n /**\n * Text written to the program's standard input, as data. A script delivered\n * this way is never quoted, escaped, or heredoc-terminated, which is the\n * whole point: quoting corruption cost the measured SWE-bench program twelve\n * probe failures and one instance's most expensive frame.\n */\n readonly stdin?: string | undefined\n /**\n * Bytes retained per captured stream. A stream that prints more keeps its\n * tail and reports what it dropped, so a command printing gigabytes costs a\n * bounded amount of memory rather than the whole of what it printed.\n *\n * Absent means unbounded, which is what a caller wants when it needs every\n * byte a tool produced (`rg --files`, `git worktree list`).\n */\n readonly maxCaptureBytes?: number | undefined\n /** Defaults to `tail`; `refuse` fails if either stream exceeds the bound. */\n readonly overflow?: \"tail\" | \"refuse\" | undefined\n}\n\n/** One captured stream: the text kept, and the bytes dropped to keep it bounded. */\ninterface Capture {\n readonly text: string\n readonly droppedBytes: number\n}\n\ninterface Tail {\n chunks: Array<Uint8Array>\n bytes: number\n dropped: number\n}\n\nconst decoder = new TextDecoder(\"utf-8\")\n\n/**\n * Joins the retained chunks and decodes them, skipping the partial code point a\n * dropped head can leave behind.\n *\n * A UTF-8 continuation byte is `10xxxxxx`, and a code point is at most four\n * bytes, so at most three leading continuation bytes can precede the first\n * whole character. Skipping them is counted as dropped rather than decoded to a\n * replacement character the process never printed.\n */\nconst decodeTail = (state: Tail): Capture => {\n const bytes = new Uint8Array(state.bytes)\n let offset = 0\n for (const chunk of state.chunks) {\n bytes.set(chunk, offset)\n offset += chunk.byteLength\n }\n if (state.dropped === 0) return { text: decoder.decode(bytes), droppedBytes: 0 }\n let start = 0\n while (start < bytes.byteLength && start < 3 && (bytes[start]! & 0b1100_0000) === 0b1000_0000) start++\n return { text: decoder.decode(bytes.subarray(start)), droppedBytes: state.dropped + start }\n}\n\nconst boundedTail = <E>(\n stream: Stream.Stream<Uint8Array, E>,\n maxBytes: number,\n overflow: \"tail\" | \"refuse\" | undefined\n): Effect.Effect<Capture, E> =>\n Stream.runFold(\n stream,\n (): Tail => ({ chunks: [], bytes: 0, dropped: 0 }),\n (state, chunk) => {\n if (chunk.byteLength === 0) return state\n state.chunks.push(chunk)\n state.bytes += chunk.byteLength\n while (state.bytes > maxBytes && state.chunks.length > 0) {\n const excess = state.bytes - maxBytes\n const first = state.chunks[0]!\n if (first.byteLength <= excess) {\n state.chunks.shift()\n state.bytes -= first.byteLength\n state.dropped += first.byteLength\n } else {\n state.chunks[0] = first.subarray(excess)\n state.bytes -= excess\n state.dropped += excess\n }\n }\n return state\n }\n ).pipe(Effect.map((state) =>\n overflow === \"refuse\" && state.dropped > 0\n ? { text: \"\", droppedBytes: state.dropped }\n : decodeTail(state)\n ))\n\nconst capture = <E>(\n stream: Stream.Stream<Uint8Array, E>,\n maxBytes: number | undefined,\n overflow: \"tail\" | \"refuse\" | undefined\n): Effect.Effect<Capture, E> =>\n maxBytes === undefined\n ? Effect.map(Stream.mkString(Stream.decodeText(stream)), (text) => ({ text, droppedBytes: 0 }))\n : boundedTail(stream, maxBytes, overflow)\n\nconst unbounded = (\n command: string,\n options: ExecOptions\n): Effect.Effect<ExecResult, ExecError, ChildProcessSpawner.ChildProcessSpawner> =>\n Effect.gen(function*() {\n const spawner = yield* ChildProcessSpawner.ChildProcessSpawner\n const settings: ChildProcess.CommandOptions = {\n ...(options.args === undefined ? { shell: true } : {}),\n ...(options.cwd === undefined ? {} : { cwd: options.cwd }),\n env: ChildProcessEnvironment.make(process.env, options.env),\n extendEnv: false,\n ...(options.stdin === undefined\n ? {}\n : { stdin: Stream.make(new TextEncoder().encode(options.stdin)) })\n }\n const handle = yield* spawner.spawn(\n options.args === undefined\n ? ChildProcess.make(command, settings)\n : ChildProcess.make(command, [...options.args], settings)\n )\n // stdout, stderr, and the exit code have to be consumed concurrently: a\n // command that fills a pipe blocks until the pipe is drained, so waiting\n // for exit first would deadlock on any output larger than the buffer.\n const [stdout, stderr, exitCode] = yield* Effect.all(\n [\n capture(handle.stdout, options.maxCaptureBytes, options.overflow),\n capture(handle.stderr, options.maxCaptureBytes, options.overflow),\n handle.exitCode\n ],\n { concurrency: \"unbounded\" }\n )\n if (options.overflow === \"refuse\") {\n const overflowed = [\n stdout.droppedBytes > 0 ? \"stdout\" : undefined,\n stderr.droppedBytes > 0 ? \"stderr\" : undefined\n ]\n .filter((stream): stream is string => stream !== undefined)\n if (overflowed.length > 0) {\n return yield* Effect.fail(\n new ExecError({\n code: \"capture_overflow\",\n message: `${command} ${\n overflowed.join(\" and \")\n } exceeded the ${options.maxCaptureBytes}-byte capture cap; refusing partial output`\n })\n )\n }\n }\n return {\n stdout: stdout.text,\n stderr: stderr.text,\n exitCode,\n stdoutDroppedBytes: stdout.droppedBytes,\n stderrDroppedBytes: stderr.droppedBytes\n }\n }).pipe(\n Effect.scoped,\n Effect.mapError((error) =>\n error instanceof ExecError ? error : new ExecError({\n code: \"spawn_error\",\n message: `exec: ${command}: ${error.message}`\n })\n )\n )\n\n/**\n * Runs a command line through the platform shell and buffers its output.\n *\n * Cancellation is scope closure: the spawn is scoped, so an interrupted fiber\n * \u2014 including the one a `timeoutMs` interrupts \u2014 terminates the process rather\n * than leaking it.\n *\n * @category execution\n * @since 1.0.0\n */\nexport const exec = (\n command: string,\n options: ExecOptions = {}\n): Effect.Effect<ExecResult, ExecError, ChildProcessSpawner.ChildProcessSpawner> =>\n options.timeoutMs === undefined\n ? unbounded(command, options)\n : Effect.timeoutOrElse(unbounded(command, options), {\n duration: options.timeoutMs,\n orElse: () =>\n Effect.fail(\n new ExecError({\n code: \"timeout\",\n message: `exec: \\`${command}\\` exceeded ${options.timeoutMs}ms`,\n limitMillis: options.timeoutMs\n })\n )\n })\n\n/**\n * The model-facing failure code a command that never produced an exit code\n * carries.\n *\n * A timeout keeps its own code, because \"the command never finished\" and \"the\n * command never started\" are different things to a caller deciding whether to\n * retry. Every other way of producing no exit code is a host failure.\n *\n * @category errors\n * @since 1.0.0\n */\nexport const toStdErrorCode = (error: ExecError): StdError.Code =>\n error.code === \"timeout\" ? \"timeout\" : \"command_failed\"\n\n/**\n * The model-facing failure one execution error becomes.\n *\n * A timeout names the command, which is what the caller asked for and all a\n * timeout has to say. Any other failure carries the message the execution\n * produced, which already names the command.\n *\n * @category errors\n * @since 1.0.0\n */\nexport const toStdError = (command: string, error: ExecError): StdError.StdError =>\n new StdError.StdError({\n code: toStdErrorCode(error),\n message: error.code === \"timeout\"\n ? `Command timed out: ${command}`\n : `Command failed to start: ${error.message}`,\n ...(error.limitMillis === undefined ? {} : { limitMillis: error.limitMillis })\n })\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -6,9 +6,9 @@
6
6
  import type { GrantStore } from "@smthrs/kernel/GrantStore";
7
7
  import * as HttpClient from "@smthrs/kernel/HttpClient";
8
8
  import * as Effect from "effect/Effect";
9
+ import * as HttpClientRequest from "effect/http/HttpClientRequest";
9
10
  import * as Schema from "effect/Schema";
10
11
  import * as Stream from "effect/Stream";
11
- import * as HttpClientRequest from "effect/unstable/http/HttpClientRequest";
12
12
  import * as StdError from "../StdError.ts";
13
13
  /**
14
14
  * Maximum captured response bytes before decoding.
@@ -1 +1 @@
1
- {"version":3,"file":"Http.d.ts","sourceRoot":"","sources":["../../../src/internal/Http.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAA;AAC3D,OAAO,KAAK,UAAU,MAAM,2BAA2B,CAAA;AACvD,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AACvC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AACvC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AACvC,OAAO,KAAK,iBAAiB,MAAM,wCAAwC,CAAA;AAC3E,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAA;AAK1C;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB,QAAkB,CAAA;AAOjD;;;;;GAKG;AACH,eAAO,MAAM,WAAW,GAAI,CAAC,EAAE,CAAC,EAC9B,QAAQ,MAAM,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC,EAAE,CAAC,CAAC,EACvC,KAAK,MAAM,KACV,MAAM,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC,GAAG,QAAQ,CAAC,QAAQ,EAAE,CAAC,CA6BlD,CAAA;AAEH;;;;;GAKG;AACH,eAAO,MAAM,YAAY,GAAI,KAAK,MAAM,EAAE,OAAO,OAAO,KAAG,QAAQ,CAAC,QAIhE,CAAA;AAEJ;;;;;GAKG;AACH,eAAO,MAAM,MAAM,GAAI,SAAS,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,EAAE,MAAM,MAAM,KAAG,MAAM,GAAG,SAGrG,CAAA;AAED;;;;;GAKG;AACH,eAAO,MAAM,OAAO,eAAkE,CAAA;AAEtF;;;;;;;;;GASG;AACH,eAAO,MAAM,YAAY,GAAI,CAAC,EAAE,CAAC,EAAE,CAAC,EAClC,QAAQ,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAC9B,KAAK,MAAM,EACX,gBAAY,EACZ,eAAe,CAAC,OAAO,EAAE,MAAM,KAAK,QAAQ,CAAC,QAAQ,KACpD,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,GAAG,QAAQ,CAAC,QAAQ,EAAE,CAAC,CAsB3C,CAAA;AAED;;;;;;GAMG;AACH,eAAO,MAAM,SAAS,GACpB,MAAM,MAAM,KACX;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAShF,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,QAAQ;;;;;EAKnB,CAAA;AAEF;;;GAGG;AACH,eAAO,MAAM,OAAO;kBAEF,MAAM;uBACD,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GAAG,SAAS;uBAC5C,MAAM,GAAG,SAAS;sBAEpB,MAAM,KAAK,iBAAiB,CAAC,iBAAiB;;;;;yDA2BjE,CAAA"}
1
+ {"version":3,"file":"Http.d.ts","sourceRoot":"","sources":["../../../src/internal/Http.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAA;AAC3D,OAAO,KAAK,UAAU,MAAM,2BAA2B,CAAA;AACvD,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AACvC,OAAO,KAAK,iBAAiB,MAAM,+BAA+B,CAAA;AAClE,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AACvC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AACvC,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAA;AAK1C;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB,QAAkB,CAAA;AAOjD;;;;;GAKG;AACH,eAAO,MAAM,WAAW,GAAI,CAAC,EAAE,CAAC,EAC9B,QAAQ,MAAM,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC,EAAE,CAAC,CAAC,EACvC,KAAK,MAAM,KACV,MAAM,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC,GAAG,QAAQ,CAAC,QAAQ,EAAE,CAAC,CA6BlD,CAAA;AAEH;;;;;GAKG;AACH,eAAO,MAAM,YAAY,GAAI,KAAK,MAAM,EAAE,OAAO,OAAO,KAAG,QAAQ,CAAC,QAIhE,CAAA;AAEJ;;;;;GAKG;AACH,eAAO,MAAM,MAAM,GAAI,SAAS,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,EAAE,MAAM,MAAM,KAAG,MAAM,GAAG,SAGrG,CAAA;AAED;;;;;GAKG;AACH,eAAO,MAAM,OAAO,eAAkE,CAAA;AAEtF;;;;;;;;;GASG;AACH,eAAO,MAAM,YAAY,GAAI,CAAC,EAAE,CAAC,EAAE,CAAC,EAClC,QAAQ,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAC9B,KAAK,MAAM,EACX,gBAAY,EACZ,eAAe,CAAC,OAAO,EAAE,MAAM,KAAK,QAAQ,CAAC,QAAQ,KACpD,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,GAAG,QAAQ,CAAC,QAAQ,EAAE,CAAC,CAsB3C,CAAA;AAED;;;;;;GAMG;AACH,eAAO,MAAM,SAAS,GACpB,MAAM,MAAM,KACX;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAShF,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,QAAQ;;;;;EAKnB,CAAA;AAEF;;;GAGG;AACH,eAAO,MAAM,OAAO;kBAEF,MAAM;uBACD,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GAAG,SAAS;uBAC5C,MAAM,GAAG,SAAS;sBAEpB,MAAM,KAAK,iBAAiB,CAAC,iBAAiB;;;;;yDA2BjE,CAAA"}
@@ -41,9 +41,9 @@ __export(Http_exports, {
41
41
  module.exports = __toCommonJS(Http_exports);
42
42
  var HttpClient = __toESM(require("@smthrs/kernel/HttpClient"), 1);
43
43
  var Effect = __toESM(require("effect/Effect"), 1);
44
+ var HttpClientRequest = __toESM(require("effect/http/HttpClientRequest"), 1);
44
45
  var Schema = __toESM(require("effect/Schema"), 1);
45
46
  var Stream = __toESM(require("effect/Stream"), 1);
46
- var HttpClientRequest = __toESM(require("effect/unstable/http/HttpClientRequest"), 1);
47
47
  var StdError = __toESM(require("../StdError.js"), 1);
48
48
  var import_HttpNetwork = require("./HttpNetwork.js");
49
49
  var import_Text = require("./Text.js");
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/internal/Http.ts"],
4
- "sourcesContent": ["/**\n * Shared HTTP response limits, error mapping, and request deadlines.\n *\n * @since 1.0.0\n */\n\nimport type { GrantStore } from \"@smthrs/kernel/GrantStore\"\nimport * as HttpClient from \"@smthrs/kernel/HttpClient\"\nimport * as Effect from \"effect/Effect\"\nimport * as Schema from \"effect/Schema\"\nimport * as Stream from \"effect/Stream\"\nimport * as HttpClientRequest from \"effect/unstable/http/HttpClientRequest\"\nimport * as StdError from \"../StdError.ts\"\nimport { guarded, refusal } from \"./HttpNetwork.ts\"\nimport { MAX_OUTPUT_BYTES, notice, truncateBytes } from \"./Text.ts\"\nimport { parseHttpUrl } from \"./Url.ts\"\n\n/**\n * Maximum captured response bytes before decoding.\n *\n * @category http\n * @since 1.0.0\n */\nexport const MAX_RESPONSE_BYTES = 5 * 1024 * 1024\n\ninterface BodyState {\n readonly chunks: Array<Uint8Array>\n size: number\n}\n\n/**\n * Reads a response up to the shared byte limit and finalizes the stream on failure.\n *\n * @category http\n * @since 1.0.0\n */\nexport const readBounded = <E, R>(\n stream: Stream.Stream<Uint8Array, E, R>,\n url: string\n): Effect.Effect<Uint8Array, E | StdError.StdError, R> =>\n Stream.runFoldEffect(\n stream,\n (): BodyState => ({ chunks: [], size: 0 }),\n (state, chunk) => {\n const size = state.size + chunk.byteLength\n if (size > MAX_RESPONSE_BYTES) {\n return Effect.fail(\n new StdError.StdError({\n code: \"response_too_large\",\n message: \"Response exceeds the 5 MiB limit\",\n path: url\n })\n )\n }\n state.chunks.push(chunk)\n state.size = size\n return Effect.succeed(state)\n }\n ).pipe(\n Effect.map((state) => {\n const output = new Uint8Array(state.size)\n let offset = 0\n for (const chunk of state.chunks) {\n output.set(chunk, offset)\n offset += chunk.byteLength\n }\n return output\n })\n )\n\n/**\n * Maps transport failures while preserving standard HTTP failure codes.\n *\n * @category http\n * @since 1.0.0\n */\nexport const requestError = (url: string, error: unknown): StdError.StdError =>\n error instanceof StdError.StdError ? error : refusal(error) ?? new StdError.StdError({\n code: \"request_failed\",\n message: `Request failed: ${url}${error instanceof Error ? ` (${error.message})` : \"\"}`\n })\n\n/**\n * Looks up a response header without depending on transport normalization.\n *\n * @category http\n * @since 1.0.0\n */\nexport const header = (headers: Readonly<Record<string, string | undefined>>, name: string): string | undefined => {\n const lower = name.toLowerCase()\n return Object.entries(headers).find(([key]) => key.toLowerCase() === lower)?.[1]\n}\n\n/**\n * Seconds; the runtime caps valid overrides at 120.\n *\n * @category http\n * @since 1.0.0\n */\nexport const Timeout = Schema.Number.check(Schema.isFinite(), Schema.isGreaterThan(0))\n\n/**\n * Bounds the entire request and body read with one timer. Interruption reaches\n * HttpClient.execute and response.stream so Effect aborts the transport and\n * finalizes the body reader before returning the timeout failure.\n * `timeoutError` preserves a tool's own timeout message while sharing the\n * validation, duration cap, and interruption behavior.\n *\n * @category http\n * @since 1.0.0\n */\nexport const withDeadline = <A, E, R>(\n effect: Effect.Effect<A, E, R>,\n url: string,\n timeout = 30,\n timeoutError?: (seconds: number) => StdError.StdError\n): Effect.Effect<A, E | StdError.StdError, R> => {\n if (!Schema.is(Timeout)(timeout)) {\n return Effect.fail(\n new StdError.StdError({\n code: \"invalid_input\",\n message: \"Timeout must be a finite number greater than zero seconds\",\n path: url\n })\n )\n }\n const seconds = Math.min(timeout, 120)\n return Effect.timeoutOrElse(effect, {\n duration: seconds * 1_000,\n orElse: () =>\n Effect.fail(\n timeoutError?.(seconds) ?? new StdError.StdError({\n code: \"timeout\",\n message: `Request timed out after ${seconds} seconds`,\n path: url\n })\n )\n })\n}\n\n/**\n * Keeps the head of rendered response text within the shared output budget and\n * discloses the cut.\n *\n * @since 1.0.0\n * @private\n */\nexport const capOutput = (\n text: string\n): { readonly text: string; readonly truncated: boolean; readonly notice?: string } => {\n const rendered = truncateBytes(text, MAX_OUTPUT_BYTES, { keep: \"head\" })\n return {\n text: rendered.text,\n truncated: rendered.truncated,\n ...(rendered.truncated\n ? { notice: notice(\"bytes\", rendered.keptBytes, rendered.keptBytes + rendered.droppedBytes) }\n : {})\n }\n}\n\n/** Shared response contract for the GET and POST tools.\n * @since 1.0.0\n * @private\n */\nexport const Response = Schema.Struct({\n status: Schema.Number.annotate({ description: \"HTTP status code, including error statuses\" }),\n body: Schema.String.annotate({ description: \"Response body as text\" }),\n truncated: Schema.Boolean.annotate({ description: \"Whether the body exceeded the display budget\" }),\n notice: Schema.optional(Schema.String.annotate({ description: \"Truncation disclosure\" }))\n})\n\n/** Validate, execute, and render one bounded HTTP request.\n * @since 1.0.0\n * @private\n */\nexport const execute = Effect.fn(\"Http.execute\")(function*(\n input: {\n readonly url: string\n readonly headers?: Readonly<Record<string, string>> | undefined\n readonly timeout?: number | undefined\n },\n makeRequest: (url: string) => HttpClientRequest.HttpClientRequest\n): Effect.fn.Return<typeof Response.Type, StdError.StdError, HttpClient.HttpClient | GrantStore> {\n const url = parseHttpUrl(input.url)\n if (url === undefined) {\n return yield* Effect.fail(\n new StdError.StdError({\n code: \"invalid_input\",\n message: `URL must use http or https without user information: ${input.url}`,\n path: input.url\n })\n )\n }\n const client = guarded(yield* HttpClient.HttpClient)\n const request = makeRequest(url.toString())\n const { status, bytes } = yield* withDeadline(\n Effect.gen(function*() {\n const response = yield* client.execute(\n input.headers === undefined ? request : HttpClientRequest.setHeaders(request, input.headers)\n )\n const bytes = yield* readBounded(response.stream, input.url)\n return { status: response.status, bytes }\n }).pipe(Effect.mapError((error) => requestError(input.url, error))),\n input.url,\n input.timeout\n )\n const { text, ...disclosure } = capOutput(new TextDecoder().decode(bytes))\n return { status, body: text, ...disclosure }\n})\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\n * Shared HTTP response limits, error mapping, and request deadlines.\n *\n * @since 1.0.0\n */\n\nimport type { GrantStore } from \"@smthrs/kernel/GrantStore\"\nimport * as HttpClient from \"@smthrs/kernel/HttpClient\"\nimport * as Effect from \"effect/Effect\"\nimport * as HttpClientRequest from \"effect/http/HttpClientRequest\"\nimport * as Schema from \"effect/Schema\"\nimport * as Stream from \"effect/Stream\"\nimport * as StdError from \"../StdError.ts\"\nimport { guarded, refusal } from \"./HttpNetwork.ts\"\nimport { MAX_OUTPUT_BYTES, notice, truncateBytes } from \"./Text.ts\"\nimport { parseHttpUrl } from \"./Url.ts\"\n\n/**\n * Maximum captured response bytes before decoding.\n *\n * @category http\n * @since 1.0.0\n */\nexport const MAX_RESPONSE_BYTES = 5 * 1024 * 1024\n\ninterface BodyState {\n readonly chunks: Array<Uint8Array>\n size: number\n}\n\n/**\n * Reads a response up to the shared byte limit and finalizes the stream on failure.\n *\n * @category http\n * @since 1.0.0\n */\nexport const readBounded = <E, R>(\n stream: Stream.Stream<Uint8Array, E, R>,\n url: string\n): Effect.Effect<Uint8Array, E | StdError.StdError, R> =>\n Stream.runFoldEffect(\n stream,\n (): BodyState => ({ chunks: [], size: 0 }),\n (state, chunk) => {\n const size = state.size + chunk.byteLength\n if (size > MAX_RESPONSE_BYTES) {\n return Effect.fail(\n new StdError.StdError({\n code: \"response_too_large\",\n message: \"Response exceeds the 5 MiB limit\",\n path: url\n })\n )\n }\n state.chunks.push(chunk)\n state.size = size\n return Effect.succeed(state)\n }\n ).pipe(\n Effect.map((state) => {\n const output = new Uint8Array(state.size)\n let offset = 0\n for (const chunk of state.chunks) {\n output.set(chunk, offset)\n offset += chunk.byteLength\n }\n return output\n })\n )\n\n/**\n * Maps transport failures while preserving standard HTTP failure codes.\n *\n * @category http\n * @since 1.0.0\n */\nexport const requestError = (url: string, error: unknown): StdError.StdError =>\n error instanceof StdError.StdError ? error : refusal(error) ?? new StdError.StdError({\n code: \"request_failed\",\n message: `Request failed: ${url}${error instanceof Error ? ` (${error.message})` : \"\"}`\n })\n\n/**\n * Looks up a response header without depending on transport normalization.\n *\n * @category http\n * @since 1.0.0\n */\nexport const header = (headers: Readonly<Record<string, string | undefined>>, name: string): string | undefined => {\n const lower = name.toLowerCase()\n return Object.entries(headers).find(([key]) => key.toLowerCase() === lower)?.[1]\n}\n\n/**\n * Seconds; the runtime caps valid overrides at 120.\n *\n * @category http\n * @since 1.0.0\n */\nexport const Timeout = Schema.Number.check(Schema.isFinite(), Schema.isGreaterThan(0))\n\n/**\n * Bounds the entire request and body read with one timer. Interruption reaches\n * HttpClient.execute and response.stream so Effect aborts the transport and\n * finalizes the body reader before returning the timeout failure.\n * `timeoutError` preserves a tool's own timeout message while sharing the\n * validation, duration cap, and interruption behavior.\n *\n * @category http\n * @since 1.0.0\n */\nexport const withDeadline = <A, E, R>(\n effect: Effect.Effect<A, E, R>,\n url: string,\n timeout = 30,\n timeoutError?: (seconds: number) => StdError.StdError\n): Effect.Effect<A, E | StdError.StdError, R> => {\n if (!Schema.is(Timeout)(timeout)) {\n return Effect.fail(\n new StdError.StdError({\n code: \"invalid_input\",\n message: \"Timeout must be a finite number greater than zero seconds\",\n path: url\n })\n )\n }\n const seconds = Math.min(timeout, 120)\n return Effect.timeoutOrElse(effect, {\n duration: seconds * 1_000,\n orElse: () =>\n Effect.fail(\n timeoutError?.(seconds) ?? new StdError.StdError({\n code: \"timeout\",\n message: `Request timed out after ${seconds} seconds`,\n path: url\n })\n )\n })\n}\n\n/**\n * Keeps the head of rendered response text within the shared output budget and\n * discloses the cut.\n *\n * @since 1.0.0\n * @private\n */\nexport const capOutput = (\n text: string\n): { readonly text: string; readonly truncated: boolean; readonly notice?: string } => {\n const rendered = truncateBytes(text, MAX_OUTPUT_BYTES, { keep: \"head\" })\n return {\n text: rendered.text,\n truncated: rendered.truncated,\n ...(rendered.truncated\n ? { notice: notice(\"bytes\", rendered.keptBytes, rendered.keptBytes + rendered.droppedBytes) }\n : {})\n }\n}\n\n/** Shared response contract for the GET and POST tools.\n * @since 1.0.0\n * @private\n */\nexport const Response = Schema.Struct({\n status: Schema.Number.annotate({ description: \"HTTP status code, including error statuses\" }),\n body: Schema.String.annotate({ description: \"Response body as text\" }),\n truncated: Schema.Boolean.annotate({ description: \"Whether the body exceeded the display budget\" }),\n notice: Schema.optional(Schema.String.annotate({ description: \"Truncation disclosure\" }))\n})\n\n/** Validate, execute, and render one bounded HTTP request.\n * @since 1.0.0\n * @private\n */\nexport const execute = Effect.fn(\"Http.execute\")(function*(\n input: {\n readonly url: string\n readonly headers?: Readonly<Record<string, string>> | undefined\n readonly timeout?: number | undefined\n },\n makeRequest: (url: string) => HttpClientRequest.HttpClientRequest\n): Effect.fn.Return<typeof Response.Type, StdError.StdError, HttpClient.HttpClient | GrantStore> {\n const url = parseHttpUrl(input.url)\n if (url === undefined) {\n return yield* Effect.fail(\n new StdError.StdError({\n code: \"invalid_input\",\n message: `URL must use http or https without user information: ${input.url}`,\n path: input.url\n })\n )\n }\n const client = guarded(yield* HttpClient.HttpClient)\n const request = makeRequest(url.toString())\n const { status, bytes } = yield* withDeadline(\n Effect.gen(function*() {\n const response = yield* client.execute(\n input.headers === undefined ? request : HttpClientRequest.setHeaders(request, input.headers)\n )\n const bytes = yield* readBounded(response.stream, input.url)\n return { status: response.status, bytes }\n }).pipe(Effect.mapError((error) => requestError(input.url, error))),\n input.url,\n input.timeout\n )\n const { text, ...disclosure } = capOutput(new TextDecoder().decode(bytes))\n return { status, body: text, ...disclosure }\n})\n"],
5
+ "mappings": "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",
6
6
  "names": ["bytes"]
7
7
  }
@@ -5,8 +5,8 @@
5
5
  */
6
6
  import { GrantStore } from "@smthrs/kernel/GrantStore";
7
7
  import { Context, Effect } from "effect";
8
- import * as HttpClient from "effect/unstable/http/HttpClient";
9
- import * as HttpClientError from "effect/unstable/http/HttpClientError";
8
+ import * as HttpClient from "effect/http/HttpClient";
9
+ import * as HttpClientError from "effect/http/HttpClientError";
10
10
  import * as StdError from "../StdError.ts";
11
11
  /** Resolver seam: all addresses must be public before an unprivileged request.
12
12
  * @since 1.0.0
@@ -1 +1 @@
1
- {"version":3,"file":"HttpNetwork.d.ts","sourceRoot":"","sources":["../../../src/internal/HttpNetwork.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAA;AAOtD,OAAO,EAAE,OAAO,EAAE,MAAM,EAAU,MAAM,QAAQ,CAAA;AAEhD,OAAO,KAAK,UAAU,MAAM,iCAAiC,CAAA;AAC7D,OAAO,KAAK,eAAe,MAAM,sCAAsC,CAAA;AAGvE,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAA;AAG1C;;;GAGG;AACH,eAAO,MAAM,WAAW,+BACX,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,CAInE,CAAA;AAwEF;;;;GAIG;AACH,eAAO,MAAM,OAAO,GAClB,QAAQ,UAAU,CAAC,UAAU,EAC7B,gBAAa,KACZ,UAAU,CAAC,UAAU,CAAC,IAAI,CAAC,eAAe,CAAC,eAAe,EAAE,UAAU,CAuBxE,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,OAAO,GAAI,OAAO,OAAO,KAAG,QAAQ,CAAC,QAAQ,GAAG,SAW5D,CAAA"}
1
+ {"version":3,"file":"HttpNetwork.d.ts","sourceRoot":"","sources":["../../../src/internal/HttpNetwork.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAA;AAOtD,OAAO,EAAE,OAAO,EAAE,MAAM,EAAU,MAAM,QAAQ,CAAA;AAEhD,OAAO,KAAK,UAAU,MAAM,wBAAwB,CAAA;AACpD,OAAO,KAAK,eAAe,MAAM,6BAA6B,CAAA;AAG9D,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAA;AAG1C;;;GAGG;AACH,eAAO,MAAM,WAAW,+BACX,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,CAInE,CAAA;AAwEF;;;;GAIG;AACH,eAAO,MAAM,OAAO,GAClB,QAAQ,UAAU,CAAC,UAAU,EAC7B,gBAAa,KACZ,UAAU,CAAC,UAAU,CAAC,IAAI,CAAC,eAAe,CAAC,eAAe,EAAE,UAAU,CAuBxE,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,OAAO,GAAI,OAAO,OAAO,KAAG,QAAQ,CAAC,QAAQ,GAAG,SAW5D,CAAA"}
@@ -37,9 +37,9 @@ var Capability = __toESM(require("@smthrs/capability/Capability"), 1);
37
37
  var import_GrantStore = require("@smthrs/kernel/GrantStore");
38
38
  var import_HttpClient = require("@smthrs/kernel/HttpClient");
39
39
  var import_effect = require("effect");
40
- var FetchHttpClient = __toESM(require("effect/unstable/http/FetchHttpClient"), 1);
41
- var HttpClient = __toESM(require("effect/unstable/http/HttpClient"), 1);
42
- var HttpClientError = __toESM(require("effect/unstable/http/HttpClientError"), 1);
40
+ var FetchHttpClient = __toESM(require("effect/http/FetchHttpClient"), 1);
41
+ var HttpClient = __toESM(require("effect/http/HttpClient"), 1);
42
+ var HttpClientError = __toESM(require("effect/http/HttpClientError"), 1);
43
43
  var import_promises = require("node:dns/promises");
44
44
  var import_node_net = require("node:net");
45
45
  var StdError = __toESM(require("../StdError.js"), 1);
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/internal/HttpNetwork.ts"],
4
- "sourcesContent": ["/**\n * Destination policy shared by the web tools, including every redirect hop.\n *\n * @since 1.0.0\n */\n\nimport * as Capability from \"@smthrs/capability/Capability\"\nimport { GrantStore } from \"@smthrs/kernel/GrantStore\"\nimport {\n authorizePreflight,\n Destination,\n fromHttpClientError,\n supportsDestinationPinning\n} from \"@smthrs/kernel/HttpClient\"\nimport { Context, Effect, Option } from \"effect\"\nimport * as FetchHttpClient from \"effect/unstable/http/FetchHttpClient\"\nimport * as HttpClient from \"effect/unstable/http/HttpClient\"\nimport * as HttpClientError from \"effect/unstable/http/HttpClientError\"\nimport { lookup } from \"node:dns/promises\"\nimport { BlockList, isIP } from \"node:net\"\nimport * as StdError from \"../StdError.ts\"\nimport { parseHttpUrl } from \"./Url.ts\"\n\n/** Resolver seam: all addresses must be public before an unprivileged request.\n * @since 1.0.0\n * @private\n */\nexport const ResolveHost = Context.Reference<\n (hostname: string) => Effect.Effect<ReadonlyArray<string>, unknown>\n>(\"@smthrs/std/HttpNetwork/ResolveHost\", {\n defaultValue: () => (hostname) =>\n Effect.tryPromise(async () => (await lookup(hostname, { all: true })).map((a) => a.address))\n})\n\nconst blocked = new BlockList()\nfor (\n const [address, prefix] of [\n [\"0.0.0.0\", 8],\n [\"10.0.0.0\", 8],\n [\"127.0.0.0\", 8],\n [\"169.254.0.0\", 16],\n [\"172.16.0.0\", 12],\n [\"192.168.0.0\", 16],\n [\"192.0.0.0\", 24],\n [\"100.64.0.0\", 10],\n [\"198.18.0.0\", 15],\n [\"224.0.0.0\", 4],\n [\"240.0.0.0\", 4]\n ] as const\n) blocked.addSubnet(address, prefix, \"ipv4\")\n// Allow global IPv6 and mapped IPv4 only, excluding transition tunnels.\nconst publicV6 = new BlockList()\npublicV6.addSubnet(\"2000::\", 3, \"ipv6\")\npublicV6.addSubnet(\"::ffff:0:0\", 96, \"ipv6\")\nblocked.addSubnet(\"2002::\", 16, \"ipv6\")\nblocked.addSubnet(\"2001::\", 32, \"ipv6\")\n\nconst isPublic = (address: string): boolean => {\n const family = isIP(address)\n if (family === 4) return !blocked.check(address, \"ipv4\")\n return family === 6 && publicV6.check(address, \"ipv6\") && !blocked.check(address, \"ipv6\")\n}\n\nconst failure = (code: StdError.Code, message: string, path: string) => new StdError.StdError({ code, message, path })\n\nconst check = Effect.fn(\"HttpNetwork.check\")(function*(value: string, client: HttpClient.HttpClient) {\n const url = parseHttpUrl(value)\n if (url === undefined) {\n return yield* Effect.fail(failure(\"invalid_input\", \"URL must use http or https without user information\", value))\n }\n if (!supportsDestinationPinning(client)) {\n return yield* Effect.fail(failure(\"unsupported\", \"HTTP host must support destination pinning\", value))\n }\n const hostname = url.hostname.replace(/^\\[|\\]$/g, \"\")\n const local = hostname.replace(/\\.$/, \"\").toLowerCase()\n const literal = isIP(hostname) !== 0\n const localhost = local === \"localhost\" || local.endsWith(\".localhost\")\n const resolve = yield* ResolveHost\n // Refuse localhost before DNS unless the origin is explicitly authorized.\n const privateGrant = Effect.gen(function*() {\n const store = yield* GrantStore\n const capability = yield* Effect.try({\n try: () => Capability.make(\"net:private\", url.origin),\n catch: () => failure(\"invalid_input\", \"Private HTTP origin exceeds the capability resource limit\", value)\n })\n yield* store.check(capability).pipe(\n Effect.mapError(() =>\n failure(\"permission_denied\", \"Private HTTP destination requires a net:private grant\", value)\n )\n )\n })\n if (localhost) yield* privateGrant\n const addresses = literal ? [hostname] : [\n ...yield* resolve(hostname).pipe(\n Effect.mapError(() => failure(\"request_failed\", \"Could not resolve HTTP destination\", value))\n )\n ]\n if (addresses.length === 0 || addresses.some((address) => isIP(address) === 0)) {\n return yield* Effect.fail(failure(\"request_failed\", \"HTTP destination has no valid addresses\", value))\n }\n if (!localhost && !addresses.every(isPublic)) yield* privateGrant\n return Object.freeze({ origin: url.origin, addresses: Object.freeze(addresses) })\n})\n\n/** Decorates the supplied client before following redirects through the guard.\n * The transport must honor manual redirects, as required by the kernel client.\n * @since 1.0.0\n * @private\n */\nexport const guarded = (\n client: HttpClient.HttpClient,\n follow = true\n): HttpClient.HttpClient.With<HttpClientError.HttpClientError, GrantStore> => {\n const checked = HttpClient.transform(\n client,\n (execute, request) =>\n authorizePreflight(\n request,\n check(request.url, client).pipe(\n Effect.mapError((cause) =>\n new HttpClientError.HttpClientError({\n reason: new HttpClientError.TransportError({ request, cause, description: cause.message })\n })\n ),\n Effect.flatMap((destination) =>\n Effect.updateContext(execute, (context: Context.Context<never>) =>\n Context.add(Context.add(context, Destination, destination), FetchHttpClient.RequestInit, {\n ...Context.getOrUndefined(context, FetchHttpClient.RequestInit),\n redirect: \"manual\"\n }))\n )\n )\n )\n )\n return follow ? HttpClient.followRedirects(checked) : checked\n}\n\n/** Recovers the typed refusal carried through Effect's HTTP error channel.\n * @since 1.0.0\n * @private\n */\nexport const refusal = (error: unknown): StdError.StdError | undefined => {\n if (!(error instanceof HttpClientError.HttpClientError) || error.reason._tag !== \"TransportError\") return undefined\n if (error.reason.cause instanceof StdError.StdError) return error.reason.cause\n if (Option.isSome(fromHttpClientError(error))) {\n return failure(\n \"permission_denied\",\n error.reason.description ?? \"HTTP permission was refused\",\n error.reason.request.url\n )\n }\n return undefined\n}\n"],
4
+ "sourcesContent": ["/**\n * Destination policy shared by the web tools, including every redirect hop.\n *\n * @since 1.0.0\n */\n\nimport * as Capability from \"@smthrs/capability/Capability\"\nimport { GrantStore } from \"@smthrs/kernel/GrantStore\"\nimport {\n authorizePreflight,\n Destination,\n fromHttpClientError,\n supportsDestinationPinning\n} from \"@smthrs/kernel/HttpClient\"\nimport { Context, Effect, Option } from \"effect\"\nimport * as FetchHttpClient from \"effect/http/FetchHttpClient\"\nimport * as HttpClient from \"effect/http/HttpClient\"\nimport * as HttpClientError from \"effect/http/HttpClientError\"\nimport { lookup } from \"node:dns/promises\"\nimport { BlockList, isIP } from \"node:net\"\nimport * as StdError from \"../StdError.ts\"\nimport { parseHttpUrl } from \"./Url.ts\"\n\n/** Resolver seam: all addresses must be public before an unprivileged request.\n * @since 1.0.0\n * @private\n */\nexport const ResolveHost = Context.Reference<\n (hostname: string) => Effect.Effect<ReadonlyArray<string>, unknown>\n>(\"@smthrs/std/HttpNetwork/ResolveHost\", {\n defaultValue: () => (hostname) =>\n Effect.tryPromise(async () => (await lookup(hostname, { all: true })).map((a) => a.address))\n})\n\nconst blocked = new BlockList()\nfor (\n const [address, prefix] of [\n [\"0.0.0.0\", 8],\n [\"10.0.0.0\", 8],\n [\"127.0.0.0\", 8],\n [\"169.254.0.0\", 16],\n [\"172.16.0.0\", 12],\n [\"192.168.0.0\", 16],\n [\"192.0.0.0\", 24],\n [\"100.64.0.0\", 10],\n [\"198.18.0.0\", 15],\n [\"224.0.0.0\", 4],\n [\"240.0.0.0\", 4]\n ] as const\n) blocked.addSubnet(address, prefix, \"ipv4\")\n// Allow global IPv6 and mapped IPv4 only, excluding transition tunnels.\nconst publicV6 = new BlockList()\npublicV6.addSubnet(\"2000::\", 3, \"ipv6\")\npublicV6.addSubnet(\"::ffff:0:0\", 96, \"ipv6\")\nblocked.addSubnet(\"2002::\", 16, \"ipv6\")\nblocked.addSubnet(\"2001::\", 32, \"ipv6\")\n\nconst isPublic = (address: string): boolean => {\n const family = isIP(address)\n if (family === 4) return !blocked.check(address, \"ipv4\")\n return family === 6 && publicV6.check(address, \"ipv6\") && !blocked.check(address, \"ipv6\")\n}\n\nconst failure = (code: StdError.Code, message: string, path: string) => new StdError.StdError({ code, message, path })\n\nconst check = Effect.fn(\"HttpNetwork.check\")(function*(value: string, client: HttpClient.HttpClient) {\n const url = parseHttpUrl(value)\n if (url === undefined) {\n return yield* Effect.fail(failure(\"invalid_input\", \"URL must use http or https without user information\", value))\n }\n if (!supportsDestinationPinning(client)) {\n return yield* Effect.fail(failure(\"unsupported\", \"HTTP host must support destination pinning\", value))\n }\n const hostname = url.hostname.replace(/^\\[|\\]$/g, \"\")\n const local = hostname.replace(/\\.$/, \"\").toLowerCase()\n const literal = isIP(hostname) !== 0\n const localhost = local === \"localhost\" || local.endsWith(\".localhost\")\n const resolve = yield* ResolveHost\n // Refuse localhost before DNS unless the origin is explicitly authorized.\n const privateGrant = Effect.gen(function*() {\n const store = yield* GrantStore\n const capability = yield* Effect.try({\n try: () => Capability.make(\"net:private\", url.origin),\n catch: () => failure(\"invalid_input\", \"Private HTTP origin exceeds the capability resource limit\", value)\n })\n yield* store.check(capability).pipe(\n Effect.mapError(() =>\n failure(\"permission_denied\", \"Private HTTP destination requires a net:private grant\", value)\n )\n )\n })\n if (localhost) yield* privateGrant\n const addresses = literal ? [hostname] : [\n ...yield* resolve(hostname).pipe(\n Effect.mapError(() => failure(\"request_failed\", \"Could not resolve HTTP destination\", value))\n )\n ]\n if (addresses.length === 0 || addresses.some((address) => isIP(address) === 0)) {\n return yield* Effect.fail(failure(\"request_failed\", \"HTTP destination has no valid addresses\", value))\n }\n if (!localhost && !addresses.every(isPublic)) yield* privateGrant\n return Object.freeze({ origin: url.origin, addresses: Object.freeze(addresses) })\n})\n\n/** Decorates the supplied client before following redirects through the guard.\n * The transport must honor manual redirects, as required by the kernel client.\n * @since 1.0.0\n * @private\n */\nexport const guarded = (\n client: HttpClient.HttpClient,\n follow = true\n): HttpClient.HttpClient.With<HttpClientError.HttpClientError, GrantStore> => {\n const checked = HttpClient.transform(\n client,\n (execute, request) =>\n authorizePreflight(\n request,\n check(request.url, client).pipe(\n Effect.mapError((cause) =>\n new HttpClientError.HttpClientError({\n reason: new HttpClientError.TransportError({ request, cause, description: cause.message })\n })\n ),\n Effect.flatMap((destination) =>\n Effect.updateContext(execute, (context: Context.Context<never>) =>\n Context.add(Context.add(context, Destination, destination), FetchHttpClient.RequestInit, {\n ...Context.getOrUndefined(context, FetchHttpClient.RequestInit),\n redirect: \"manual\"\n }))\n )\n )\n )\n )\n return follow ? HttpClient.followRedirects(checked) : checked\n}\n\n/** Recovers the typed refusal carried through Effect's HTTP error channel.\n * @since 1.0.0\n * @private\n */\nexport const refusal = (error: unknown): StdError.StdError | undefined => {\n if (!(error instanceof HttpClientError.HttpClientError) || error.reason._tag !== \"TransportError\") return undefined\n if (error.reason.cause instanceof StdError.StdError) return error.reason.cause\n if (Option.isSome(fromHttpClientError(error))) {\n return failure(\n \"permission_denied\",\n error.reason.description ?? \"HTTP permission was refused\",\n error.reason.request.url\n )\n }\n return undefined\n}\n"],
5
5
  "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -10,7 +10,7 @@
10
10
  import * as Credential from "@smthrs/control/Credential";
11
11
  import * as HttpClient from "@smthrs/kernel/HttpClient";
12
12
  import { Clock, Effect, Layer, Redacted, Schema } from "effect";
13
- import * as HttpClientRequest from "effect/unstable/http/HttpClientRequest";
13
+ import * as HttpClientRequest from "effect/http/HttpClientRequest";
14
14
  import { header, readBounded } from "./internal/Http.js";
15
15
  import * as StdError from "./StdError.js";
16
16
  import * as WebSearch from "./WebSearch.js";
@@ -1 +1 @@
1
- {"version":3,"file":"ExaWebSearch.js","sourceRoot":"","sources":["../../src/ExaWebSearch.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The Exa provider for the `websearch` flow.\n *\n * {@link layer} binds `WebSearch.WebSearch` to the Exa search API. It reads the\n * API key from a named credential on every search, calls Exa through the\n * permission-checked `HttpClient`, and maps each hit onto `WebSearch.Result`.\n *\n * @since 1.0.0\n */\n\nimport * as Credential from \"@smthrs/control/Credential\"\nimport * as HttpClient from \"@smthrs/kernel/HttpClient\"\nimport { Clock, Effect, Layer, Redacted, Schema } from \"effect\"\nimport * as HttpClientRequest from \"effect/unstable/http/HttpClientRequest\"\nimport { header, readBounded } from \"./internal/Http.ts\"\nimport * as StdError from \"./StdError.ts\"\nimport * as WebSearch from \"./WebSearch.ts\"\n\nconst maxResults = 20\nconst requestTimeoutMs = 30_000\nconst ExaResult = Schema.Struct({\n title: Schema.optional(Schema.String),\n url: Schema.String,\n text: Schema.optional(Schema.String),\n publishedDate: Schema.optional(Schema.String)\n})\nconst ExaResponse = Schema.Struct({\n results: Schema.Array(ExaResult)\n})\nconst freshnessDays = {\n day: 1,\n week: 7,\n month: 31,\n year: 365\n} as const\n\nconst failure = (code: StdError.Code, message: string): StdError.StdError => new StdError.StdError({ code, message })\n\n/**\n * Provides {@link WebSearch.WebSearch} backed by the Exa API, reading its\n * key from the named credential.\n *\n * @category layers\n * @since 1.0.0\n */\nexport const layer = (\n credentialId: string\n): Layer.Layer<WebSearch.WebSearch, never, Credential.Credential | HttpClient.HttpClient> =>\n Layer.effect(\n WebSearch.WebSearch,\n Effect.gen(function*() {\n const credentials = yield* Credential.Credential\n const http = yield* HttpClient.HttpClient\n return WebSearch.make({\n search: (input): Effect.Effect<typeof WebSearch.Output.Type, StdError.StdError> =>\n Effect.gen(function*() {\n const reference = yield* credentials.get(credentialId).pipe(Effect.mapError(() =>\n new StdError.StdError({\n code: \"provider_unavailable\",\n message: \"Configured Exa credential is unavailable\"\n })\n ))\n const secret = yield* credentials.resolve(reference).pipe(Effect.mapError(() =>\n new StdError.StdError({\n code: \"provider_unavailable\",\n message: \"Configured Exa credential cannot be resolved\"\n })\n ))\n const now = yield* Clock.currentTimeMillis\n const request = HttpClientRequest.setHeaders(\n HttpClientRequest.bodyJsonUnsafe(HttpClientRequest.post(\"https://api.exa.ai/search\"), {\n query: input.query,\n numResults: Math.min(input.numResults ?? 8, maxResults),\n ...(input.freshness === undefined\n ? {}\n : { startPublishedDate: new Date(now - freshnessDays[input.freshness] * 86_400_000).toISOString() })\n }),\n { \"authorization\": `Bearer ${Redacted.value(secret)}`, \"content-type\": \"application/json\" }\n )\n const response = yield* http.execute(request).pipe(\n Effect.timeout(requestTimeoutMs),\n Effect.mapError((error) =>\n error._tag === \"TimeoutError\"\n ? failure(\"timeout\", \"Exa search request timed out\")\n : failure(\"request_failed\", \"Exa search request failed\")\n )\n )\n const retryAfter = header(response.headers, \"retry-after\")\n // Successful responses may carry pacing advice too; status decides refusal.\n const refused = response.status < 200 || response.status >= 300\n if (response.status === 429 || (refused && retryAfter !== undefined)) {\n const delay = retryAfter === undefined\n ? NaN\n : /^\\d+$/.test(retryAfter.trim())\n ? Number(retryAfter)\n : Math.max(0, Math.ceil((Date.parse(retryAfter) - (yield* Clock.currentTimeMillis)) / 1_000))\n return yield* Effect.fail(\n failure(\n \"rate_limited\",\n Number.isFinite(delay)\n ? `Exa search was throttled; retry after ${delay} seconds`\n : \"Exa search was throttled\"\n )\n )\n }\n if (response.status === 401 || response.status === 403) {\n return yield* Effect.fail(failure(\"provider_unavailable\", \"Exa search authentication was rejected\"))\n }\n if (response.status >= 500) {\n return yield* Effect.fail(failure(\"provider_unavailable\", `Exa search returned ${response.status}`))\n }\n if (response.status < 200 || response.status >= 300) {\n return yield* Effect.fail(failure(\"request_failed\", `Exa search returned ${response.status}`))\n }\n // Bound the body before decoding: an endpoint must not choose how\n // much of it the host buffers.\n const bytes = yield* readBounded(response.stream, \"https://api.exa.ai/search\").pipe(\n Effect.timeout(requestTimeoutMs),\n Effect.mapError((error) =>\n error._tag === \"TimeoutError\"\n ? failure(\"timeout\", \"Exa search response timed out\")\n : error instanceof StdError.StdError && error.code === \"response_too_large\"\n ? failure(\"response_too_large\", \"Exa search response exceeds the 5 MiB limit\")\n : failure(\"request_failed\", \"Exa search response was invalid\")\n )\n )\n const body = yield* Schema.decodeUnknownEffect(Schema.fromJsonString(ExaResponse))(\n new TextDecoder().decode(bytes)\n ).pipe(\n Effect.mapError(() =>\n new StdError.StdError({ code: \"request_failed\", message: \"Exa search response was invalid\" })\n )\n )\n return {\n results: body.results.slice(0, Math.min(input.numResults ?? 8, maxResults)).map((result) => ({\n title: result.title ?? result.url,\n url: result.url,\n snippet: (result.text ?? \"\").slice(0, 2_000),\n ...(result.publishedDate === undefined ? {} : { publishedAt: result.publishedDate })\n }))\n }\n })\n })\n })\n )\n"]}
1
+ {"version":3,"file":"ExaWebSearch.js","sourceRoot":"","sources":["../../src/ExaWebSearch.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,UAAU,MAAM,4BAA4B,CAAA;AACxD,OAAO,KAAK,UAAU,MAAM,2BAA2B,CAAA;AACvD,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAC/D,OAAO,KAAK,iBAAiB,MAAM,+BAA+B,CAAA;AAClE,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AACxD,OAAO,KAAK,QAAQ,MAAM,eAAe,CAAA;AACzC,OAAO,KAAK,SAAS,MAAM,gBAAgB,CAAA;AAE3C,MAAM,UAAU,GAAG,EAAE,CAAA;AACrB,MAAM,gBAAgB,GAAG,MAAM,CAAA;AAC/B,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC;IAC9B,KAAK,EAAE,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC;IACrC,GAAG,EAAE,MAAM,CAAC,MAAM;IAClB,IAAI,EAAE,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC;IACpC,aAAa,EAAE,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC;CAC9C,CAAC,CAAA;AACF,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,CAAC;IAChC,OAAO,EAAE,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC;CACjC,CAAC,CAAA;AACF,MAAM,aAAa,GAAG;IACpB,GAAG,EAAE,CAAC;IACN,IAAI,EAAE,CAAC;IACP,KAAK,EAAE,EAAE;IACT,IAAI,EAAE,GAAG;CACD,CAAA;AAEV,MAAM,OAAO,GAAG,CAAC,IAAmB,EAAE,OAAe,EAAqB,EAAE,CAAC,IAAI,QAAQ,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAA;AAErH;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,KAAK,GAAG,CACnB,YAAoB,EACoE,EAAE,CAC1F,KAAK,CAAC,MAAM,CACV,SAAS,CAAC,SAAS,EACnB,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;IAClB,MAAM,WAAW,GAAG,KAAK,CAAC,CAAC,UAAU,CAAC,UAAU,CAAA;IAChD,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,UAAU,CAAC,UAAU,CAAA;IACzC,OAAO,SAAS,CAAC,IAAI,CAAC;QACpB,MAAM,EAAE,CAAC,KAAK,EAAkE,EAAE,CAChF,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;YAClB,MAAM,SAAS,GAAG,KAAK,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,EAAE,CAC/E,IAAI,QAAQ,CAAC,QAAQ,CAAC;gBACpB,IAAI,EAAE,sBAAsB;gBAC5B,OAAO,EAAE,0CAA0C;aACpD,CAAC,CACH,CAAC,CAAA;YACF,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,WAAW,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,EAAE,CAC7E,IAAI,QAAQ,CAAC,QAAQ,CAAC;gBACpB,IAAI,EAAE,sBAAsB;gBAC5B,OAAO,EAAE,8CAA8C;aACxD,CAAC,CACH,CAAC,CAAA;YACF,MAAM,GAAG,GAAG,KAAK,CAAC,CAAC,KAAK,CAAC,iBAAiB,CAAA;YAC1C,MAAM,OAAO,GAAG,iBAAiB,CAAC,UAAU,CAC1C,iBAAiB,CAAC,cAAc,CAAC,iBAAiB,CAAC,IAAI,CAAC,2BAA2B,CAAC,EAAE;gBACpF,KAAK,EAAE,KAAK,CAAC,KAAK;gBAClB,UAAU,EAAE,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,UAAU,IAAI,CAAC,EAAE,UAAU,CAAC;gBACvD,GAAG,CAAC,KAAK,CAAC,SAAS,KAAK,SAAS;oBAC/B,CAAC,CAAC,EAAE;oBACJ,CAAC,CAAC,EAAE,kBAAkB,EAAE,IAAI,IAAI,CAAC,GAAG,GAAG,aAAa,CAAC,KAAK,CAAC,SAAS,CAAC,GAAG,UAAU,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC;aACvG,CAAC,EACF,EAAE,eAAe,EAAE,UAAU,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAC5F,CAAA;YACD,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,IAAI,CAChD,MAAM,CAAC,OAAO,CAAC,gBAAgB,CAAC,EAChC,MAAM,CAAC,QAAQ,CAAC,CAAC,KAAK,EAAE,EAAE,CACxB,KAAK,CAAC,IAAI,KAAK,cAAc;gBAC3B,CAAC,CAAC,OAAO,CAAC,SAAS,EAAE,8BAA8B,CAAC;gBACpD,CAAC,CAAC,OAAO,CAAC,gBAAgB,EAAE,2BAA2B,CAAC,CAC3D,CACF,CAAA;YACD,MAAM,UAAU,GAAG,MAAM,CAAC,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC,CAAA;YAC1D,4EAA4E;YAC5E,MAAM,OAAO,GAAG,QAAQ,CAAC,MAAM,GAAG,GAAG,IAAI,QAAQ,CAAC,MAAM,IAAI,GAAG,CAAA;YAC/D,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,IAAI,UAAU,KAAK,SAAS,CAAC,EAAE,CAAC;gBACrE,MAAM,KAAK,GAAG,UAAU,KAAK,SAAS;oBACpC,CAAC,CAAC,GAAG;oBACL,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC;wBACjC,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC;wBACpB,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAA;gBAC/F,OAAO,KAAK,CAAC,CAAC,MAAM,CAAC,IAAI,CACvB,OAAO,CACL,cAAc,EACd,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC;oBACpB,CAAC,CAAC,yCAAyC,KAAK,UAAU;oBAC1D,CAAC,CAAC,0BAA0B,CAC/B,CACF,CAAA;YACH,CAAC;YACD,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;gBACvD,OAAO,KAAK,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,sBAAsB,EAAE,wCAAwC,CAAC,CAAC,CAAA;YACtG,CAAC;YACD,IAAI,QAAQ,CAAC,MAAM,IAAI,GAAG,EAAE,CAAC;gBAC3B,OAAO,KAAK,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,sBAAsB,EAAE,uBAAuB,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC,CAAA;YACtG,CAAC;YACD,IAAI,QAAQ,CAAC,MAAM,GAAG,GAAG,IAAI,QAAQ,CAAC,MAAM,IAAI,GAAG,EAAE,CAAC;gBACpD,OAAO,KAAK,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,gBAAgB,EAAE,uBAAuB,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC,CAAA;YAChG,CAAC;YACD,kEAAkE;YAClE,+BAA+B;YAC/B,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,WAAW,CAAC,QAAQ,CAAC,MAAM,EAAE,2BAA2B,CAAC,CAAC,IAAI,CACjF,MAAM,CAAC,OAAO,CAAC,gBAAgB,CAAC,EAChC,MAAM,CAAC,QAAQ,CAAC,CAAC,KAAK,EAAE,EAAE,CACxB,KAAK,CAAC,IAAI,KAAK,cAAc;gBAC3B,CAAC,CAAC,OAAO,CAAC,SAAS,EAAE,+BAA+B,CAAC;gBACrD,CAAC,CAAC,KAAK,YAAY,QAAQ,CAAC,QAAQ,IAAI,KAAK,CAAC,IAAI,KAAK,oBAAoB;oBAC3E,CAAC,CAAC,OAAO,CAAC,oBAAoB,EAAE,6CAA6C,CAAC;oBAC9E,CAAC,CAAC,OAAO,CAAC,gBAAgB,EAAE,iCAAiC,CAAC,CACjE,CACF,CAAA;YACD,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,mBAAmB,CAAC,MAAM,CAAC,cAAc,CAAC,WAAW,CAAC,CAAC,CAChF,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAChC,CAAC,IAAI,CACJ,MAAM,CAAC,QAAQ,CAAC,GAAG,EAAE,CACnB,IAAI,QAAQ,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,gBAAgB,EAAE,OAAO,EAAE,iCAAiC,EAAE,CAAC,CAC9F,CACF,CAAA;YACD,OAAO;gBACL,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,UAAU,IAAI,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;oBAC3F,KAAK,EAAE,MAAM,CAAC,KAAK,IAAI,MAAM,CAAC,GAAG;oBACjC,GAAG,EAAE,MAAM,CAAC,GAAG;oBACf,OAAO,EAAE,CAAC,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC;oBAC5C,GAAG,CAAC,MAAM,CAAC,aAAa,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,MAAM,CAAC,aAAa,EAAE,CAAC;iBACrF,CAAC,CAAC;aACJ,CAAA;QACH,CAAC,CAAC;KACL,CAAC,CAAA;AACJ,CAAC,CAAC,CACH,CAAA","sourcesContent":["/**\n * The Exa provider for the `websearch` flow.\n *\n * {@link layer} binds `WebSearch.WebSearch` to the Exa search API. It reads the\n * API key from a named credential on every search, calls Exa through the\n * permission-checked `HttpClient`, and maps each hit onto `WebSearch.Result`.\n *\n * @since 1.0.0\n */\n\nimport * as Credential from \"@smthrs/control/Credential\"\nimport * as HttpClient from \"@smthrs/kernel/HttpClient\"\nimport { Clock, Effect, Layer, Redacted, Schema } from \"effect\"\nimport * as HttpClientRequest from \"effect/http/HttpClientRequest\"\nimport { header, readBounded } from \"./internal/Http.ts\"\nimport * as StdError from \"./StdError.ts\"\nimport * as WebSearch from \"./WebSearch.ts\"\n\nconst maxResults = 20\nconst requestTimeoutMs = 30_000\nconst ExaResult = Schema.Struct({\n title: Schema.optional(Schema.String),\n url: Schema.String,\n text: Schema.optional(Schema.String),\n publishedDate: Schema.optional(Schema.String)\n})\nconst ExaResponse = Schema.Struct({\n results: Schema.Array(ExaResult)\n})\nconst freshnessDays = {\n day: 1,\n week: 7,\n month: 31,\n year: 365\n} as const\n\nconst failure = (code: StdError.Code, message: string): StdError.StdError => new StdError.StdError({ code, message })\n\n/**\n * Provides {@link WebSearch.WebSearch} backed by the Exa API, reading its\n * key from the named credential.\n *\n * @category layers\n * @since 1.0.0\n */\nexport const layer = (\n credentialId: string\n): Layer.Layer<WebSearch.WebSearch, never, Credential.Credential | HttpClient.HttpClient> =>\n Layer.effect(\n WebSearch.WebSearch,\n Effect.gen(function*() {\n const credentials = yield* Credential.Credential\n const http = yield* HttpClient.HttpClient\n return WebSearch.make({\n search: (input): Effect.Effect<typeof WebSearch.Output.Type, StdError.StdError> =>\n Effect.gen(function*() {\n const reference = yield* credentials.get(credentialId).pipe(Effect.mapError(() =>\n new StdError.StdError({\n code: \"provider_unavailable\",\n message: \"Configured Exa credential is unavailable\"\n })\n ))\n const secret = yield* credentials.resolve(reference).pipe(Effect.mapError(() =>\n new StdError.StdError({\n code: \"provider_unavailable\",\n message: \"Configured Exa credential cannot be resolved\"\n })\n ))\n const now = yield* Clock.currentTimeMillis\n const request = HttpClientRequest.setHeaders(\n HttpClientRequest.bodyJsonUnsafe(HttpClientRequest.post(\"https://api.exa.ai/search\"), {\n query: input.query,\n numResults: Math.min(input.numResults ?? 8, maxResults),\n ...(input.freshness === undefined\n ? {}\n : { startPublishedDate: new Date(now - freshnessDays[input.freshness] * 86_400_000).toISOString() })\n }),\n { \"authorization\": `Bearer ${Redacted.value(secret)}`, \"content-type\": \"application/json\" }\n )\n const response = yield* http.execute(request).pipe(\n Effect.timeout(requestTimeoutMs),\n Effect.mapError((error) =>\n error._tag === \"TimeoutError\"\n ? failure(\"timeout\", \"Exa search request timed out\")\n : failure(\"request_failed\", \"Exa search request failed\")\n )\n )\n const retryAfter = header(response.headers, \"retry-after\")\n // Successful responses may carry pacing advice too; status decides refusal.\n const refused = response.status < 200 || response.status >= 300\n if (response.status === 429 || (refused && retryAfter !== undefined)) {\n const delay = retryAfter === undefined\n ? NaN\n : /^\\d+$/.test(retryAfter.trim())\n ? Number(retryAfter)\n : Math.max(0, Math.ceil((Date.parse(retryAfter) - (yield* Clock.currentTimeMillis)) / 1_000))\n return yield* Effect.fail(\n failure(\n \"rate_limited\",\n Number.isFinite(delay)\n ? `Exa search was throttled; retry after ${delay} seconds`\n : \"Exa search was throttled\"\n )\n )\n }\n if (response.status === 401 || response.status === 403) {\n return yield* Effect.fail(failure(\"provider_unavailable\", \"Exa search authentication was rejected\"))\n }\n if (response.status >= 500) {\n return yield* Effect.fail(failure(\"provider_unavailable\", `Exa search returned ${response.status}`))\n }\n if (response.status < 200 || response.status >= 300) {\n return yield* Effect.fail(failure(\"request_failed\", `Exa search returned ${response.status}`))\n }\n // Bound the body before decoding: an endpoint must not choose how\n // much of it the host buffers.\n const bytes = yield* readBounded(response.stream, \"https://api.exa.ai/search\").pipe(\n Effect.timeout(requestTimeoutMs),\n Effect.mapError((error) =>\n error._tag === \"TimeoutError\"\n ? failure(\"timeout\", \"Exa search response timed out\")\n : error instanceof StdError.StdError && error.code === \"response_too_large\"\n ? failure(\"response_too_large\", \"Exa search response exceeds the 5 MiB limit\")\n : failure(\"request_failed\", \"Exa search response was invalid\")\n )\n )\n const body = yield* Schema.decodeUnknownEffect(Schema.fromJsonString(ExaResponse))(\n new TextDecoder().decode(bytes)\n ).pipe(\n Effect.mapError(() =>\n new StdError.StdError({ code: \"request_failed\", message: \"Exa search response was invalid\" })\n )\n )\n return {\n results: body.results.slice(0, Math.min(input.numResults ?? 8, maxResults)).map((result) => ({\n title: result.title ?? result.url,\n url: result.url,\n snippet: (result.text ?? \"\").slice(0, 2_000),\n ...(result.publishedDate === undefined ? {} : { publishedAt: result.publishedDate })\n }))\n }\n })\n })\n })\n )\n"]}
@@ -126,5 +126,5 @@ export declare const run: (input: {
126
126
  readonly body: string;
127
127
  readonly truncated: boolean;
128
128
  readonly notice?: string | undefined;
129
- }, import("./StdError.ts").StdError, import("@smthrs/kernel/GrantStore").GrantStore | import("@smthrs/kernel/HttpClient").HttpClient>;
129
+ }, import("./StdError.ts").StdError, import("@smthrs/kernel/GrantStore").GrantStore | import("effect/http/HttpClient").HttpClient>;
130
130
  //# sourceMappingURL=Fetch.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Fetch.d.ts","sourceRoot":"","sources":["../../src/Fetch.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AACvC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AAKvC;;;;;GAKG;AACH,eAAO,MAAM,IAAI,UAAU,CAAA;AAE3B;;;;;GAKG;AACH,eAAO,MAAM,WAAW,kIACyG,CAAA;AAEjI;;;;;GAKG;AACH,eAAO,MAAM,KAAK;;;;EAQhB,CAAA;AAEF;;;;;GAKG;AACH,MAAM,MAAM,KAAK,GAAG,OAAO,KAAK,CAAC,IAAI,CAAA;AAErC;;;;;GAKG;AACH,eAAO,MAAM,MAAM;;;;;EAAW,CAAA;AAE9B;;;;;GAKG;AACH,MAAM,MAAM,MAAM,GAAG,OAAO,MAAM,CAAC,IAAI,CAAA;AAEvC;;;;;;;;GAQG;AACH,eAAO,MAAM,OAAO,4CAAwE,CAAA;AAE5F;;;;;;;;GAQG;AACH,eAAO,MAAM,UAAU,GAAI,QAAQ,OAAO,KAAK,CAAC,IAAI,+CAAY,CAAA;AAEhE;;;;;GAKG;AACH,eAAO,MAAM,YAAY,UAA+B,CAAA;AAExD;;;;;GAKG;AACH,eAAO,MAAM,IAAI;;;;;;;;;;;;;;;;CAAsF,CAAA;AAEvG;;;;;;;;GAQG;AACH,eAAO,MAAM,GAAG;;;;;;;;;;;qIAAkF,CAAA"}
1
+ {"version":3,"file":"Fetch.d.ts","sourceRoot":"","sources":["../../src/Fetch.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AAEvC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AAIvC;;;;;GAKG;AACH,eAAO,MAAM,IAAI,UAAU,CAAA;AAE3B;;;;;GAKG;AACH,eAAO,MAAM,WAAW,kIACyG,CAAA;AAEjI;;;;;GAKG;AACH,eAAO,MAAM,KAAK;;;;EAQhB,CAAA;AAEF;;;;;GAKG;AACH,MAAM,MAAM,KAAK,GAAG,OAAO,KAAK,CAAC,IAAI,CAAA;AAErC;;;;;GAKG;AACH,eAAO,MAAM,MAAM;;;;;EAAW,CAAA;AAE9B;;;;;GAKG;AACH,MAAM,MAAM,MAAM,GAAG,OAAO,MAAM,CAAC,IAAI,CAAA;AAEvC;;;;;;;;GAQG;AACH,eAAO,MAAM,OAAO,4CAAwE,CAAA;AAE5F;;;;;;;;GAQG;AACH,eAAO,MAAM,UAAU,GAAI,QAAQ,OAAO,KAAK,CAAC,IAAI,+CAAY,CAAA;AAEhE;;;;;GAKG;AACH,eAAO,MAAM,YAAY,UAA+B,CAAA;AAExD;;;;;GAKG;AACH,eAAO,MAAM,IAAI;;;;;;;;;;;;;;;;CAAsF,CAAA;AAEvG;;;;;;;;GAQG;AACH,eAAO,MAAM,GAAG;;;;;;;;;;;kIAAkF,CAAA"}
package/dist/esm/Fetch.js CHANGED
@@ -4,8 +4,8 @@
4
4
  * @since 1.0.0
5
5
  */
6
6
  import * as Effect from "effect/Effect";
7
+ import * as HttpClientRequest from "effect/http/HttpClientRequest";
7
8
  import * as Schema from "effect/Schema";
8
- import * as HttpClientRequest from "effect/unstable/http/HttpClientRequest";
9
9
  import { capability, envelope } from "./internal/Declaration.js";
10
10
  import { execute, Response, Timeout } from "./internal/Http.js";
11
11
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"Fetch.js","sourceRoot":"","sources":["../../src/Fetch.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AACvC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AACvC,OAAO,KAAK,iBAAiB,MAAM,wCAAwC,CAAA;AAC3E,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAA;AAChE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAA;AAE/D;;;;;GAKG;AACH,MAAM,CAAC,MAAM,IAAI,GAAG,OAAO,CAAA;AAE3B;;;;;GAKG;AACH,MAAM,CAAC,MAAM,WAAW,GACtB,+HAA+H,CAAA;AAEjI;;;;;GAKG;AACH,MAAM,CAAC,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC;IACjC,GAAG,EAAE,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,WAAW,EAAE,wCAAwC,EAAE,CAAC;IACtF,OAAO,EAAE,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC;QAC7E,WAAW,EAAE,4BAA4B;KAC1C,CAAC;IACF,OAAO,EAAE,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,QAAQ,CAAC;QACzC,WAAW,EAAE,mFAAmF;KACjG,CAAC;CACH,CAAC,CAAA;AAUF;;;;;GAKG;AACH,MAAM,CAAC,MAAM,MAAM,GAAG,QAAQ,CAAA;AAU9B;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,OAAO,GAAG,QAAQ,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,CAAA;AAE5F;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,MAAyB,EAAE,EAAE,CAAC,OAAO,CAAA;AAEhE;;;;;GAKG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,UAAU,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC,CAAA;AAExD;;;;;GAKG;AACH,MAAM,CAAC,MAAM,IAAI,GAAG,EAAE,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,OAAO,EAAW,CAAA;AAEvG;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,GAAG,GAAG,MAAM,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC,KAAY,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,EAAE,iBAAiB,CAAC,GAAG,CAAC,CAAC,CAAA","sourcesContent":["/**\n * HTTP GET flow declaration and portable handler.\n *\n * @since 1.0.0\n */\n\nimport * as Effect from \"effect/Effect\"\nimport * as Schema from \"effect/Schema\"\nimport * as HttpClientRequest from \"effect/unstable/http/HttpClientRequest\"\nimport { capability, envelope } from \"./internal/Declaration.ts\"\nimport { execute, Response, Timeout } from \"./internal/Http.ts\"\n\n/**\n * Registry name for the fetch flow.\n *\n * @category identifiers\n * @since 1.0.0\n */\nexport const name = \"fetch\"\n\n/**\n * Model-facing description of the fetch flow.\n *\n * @category descriptions\n * @since 1.0.0\n */\nexport const description =\n \"Get an absolute URL and return its status and text body; long bodies are truncated with a notice. Use http-post to send data.\"\n\n/**\n * Input schema for the fetch flow.\n *\n * @category schemas\n * @since 1.0.0\n */\nexport const Input = Schema.Struct({\n url: Schema.String.annotate({ description: \"Absolute http or https URL to retrieve\" }),\n headers: Schema.optional(Schema.Record(Schema.String, Schema.String)).annotate({\n description: \"Additional request headers\"\n }),\n timeout: Schema.optional(Timeout).annotate({\n description: \"Total request and response body timeout in seconds; defaults to 30, capped at 120\"\n })\n})\n\n/**\n * Decoded input accepted by the `fetch` flow.\n *\n * @category models\n * @since 1.0.0\n */\nexport type Input = typeof Input.Type\n\n/**\n * Output schema for the fetch flow.\n *\n * @category schemas\n * @since 1.0.0\n */\nexport const Output = Response\n\n/**\n * Decoded output returned by the `fetch` flow.\n *\n * @category models\n * @since 1.0.0\n */\nexport type Output = typeof Output.Type\n\n/**\n * Static effect envelope for the fetch flow.\n *\n * A retrieval leaves no durable state behind, so it is sealed even though it\n * leaves the machine.\n *\n * @category effects\n * @since 1.0.0\n */\nexport const effects = envelope({ tier: \"sealed\", mode: \"expected\", reads: [], writes: [] })\n\n/**\n * Narrows the fetch effect envelope for one decoded input.\n *\n * Network reach is expressed as a capability rather than a path envelope, so\n * a retrieval has nothing left to narrow.\n *\n * @category effects\n * @since 1.0.0\n */\nexport const effectsFor = (_input: typeof Input.Type) => effects\n\n/**\n * Capabilities required by the fetch flow.\n *\n * @category capabilities\n * @since 1.0.0\n */\nexport const capabilities = [capability(\"net:get\", \"*\")]\n\n/**\n * Declaration-only fetch flow.\n *\n * @category flows\n * @since 1.0.0\n */\nexport const flow = { name, description, input: Input, output: Output, capabilities, effects } as const\n\n/**\n * Retrieves a URL through the permission-aware kernel HTTP client.\n *\n * Error statuses are ordinary results; only transport, permission, and body\n * decoding failures use the typed error channel.\n *\n * @category handlers\n * @since 1.0.0\n */\nexport const run = Effect.fn(\"Fetch.run\")((input: Input) => execute(input, HttpClientRequest.get))\n"]}
1
+ {"version":3,"file":"Fetch.js","sourceRoot":"","sources":["../../src/Fetch.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AACvC,OAAO,KAAK,iBAAiB,MAAM,+BAA+B,CAAA;AAClE,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AACvC,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAA;AAChE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAA;AAE/D;;;;;GAKG;AACH,MAAM,CAAC,MAAM,IAAI,GAAG,OAAO,CAAA;AAE3B;;;;;GAKG;AACH,MAAM,CAAC,MAAM,WAAW,GACtB,+HAA+H,CAAA;AAEjI;;;;;GAKG;AACH,MAAM,CAAC,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC;IACjC,GAAG,EAAE,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,WAAW,EAAE,wCAAwC,EAAE,CAAC;IACtF,OAAO,EAAE,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC;QAC7E,WAAW,EAAE,4BAA4B;KAC1C,CAAC;IACF,OAAO,EAAE,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,QAAQ,CAAC;QACzC,WAAW,EAAE,mFAAmF;KACjG,CAAC;CACH,CAAC,CAAA;AAUF;;;;;GAKG;AACH,MAAM,CAAC,MAAM,MAAM,GAAG,QAAQ,CAAA;AAU9B;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,OAAO,GAAG,QAAQ,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,CAAA;AAE5F;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,MAAyB,EAAE,EAAE,CAAC,OAAO,CAAA;AAEhE;;;;;GAKG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,UAAU,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC,CAAA;AAExD;;;;;GAKG;AACH,MAAM,CAAC,MAAM,IAAI,GAAG,EAAE,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,OAAO,EAAW,CAAA;AAEvG;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,GAAG,GAAG,MAAM,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC,KAAY,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,EAAE,iBAAiB,CAAC,GAAG,CAAC,CAAC,CAAA","sourcesContent":["/**\n * HTTP GET flow declaration and portable handler.\n *\n * @since 1.0.0\n */\n\nimport * as Effect from \"effect/Effect\"\nimport * as HttpClientRequest from \"effect/http/HttpClientRequest\"\nimport * as Schema from \"effect/Schema\"\nimport { capability, envelope } from \"./internal/Declaration.ts\"\nimport { execute, Response, Timeout } from \"./internal/Http.ts\"\n\n/**\n * Registry name for the fetch flow.\n *\n * @category identifiers\n * @since 1.0.0\n */\nexport const name = \"fetch\"\n\n/**\n * Model-facing description of the fetch flow.\n *\n * @category descriptions\n * @since 1.0.0\n */\nexport const description =\n \"Get an absolute URL and return its status and text body; long bodies are truncated with a notice. Use http-post to send data.\"\n\n/**\n * Input schema for the fetch flow.\n *\n * @category schemas\n * @since 1.0.0\n */\nexport const Input = Schema.Struct({\n url: Schema.String.annotate({ description: \"Absolute http or https URL to retrieve\" }),\n headers: Schema.optional(Schema.Record(Schema.String, Schema.String)).annotate({\n description: \"Additional request headers\"\n }),\n timeout: Schema.optional(Timeout).annotate({\n description: \"Total request and response body timeout in seconds; defaults to 30, capped at 120\"\n })\n})\n\n/**\n * Decoded input accepted by the `fetch` flow.\n *\n * @category models\n * @since 1.0.0\n */\nexport type Input = typeof Input.Type\n\n/**\n * Output schema for the fetch flow.\n *\n * @category schemas\n * @since 1.0.0\n */\nexport const Output = Response\n\n/**\n * Decoded output returned by the `fetch` flow.\n *\n * @category models\n * @since 1.0.0\n */\nexport type Output = typeof Output.Type\n\n/**\n * Static effect envelope for the fetch flow.\n *\n * A retrieval leaves no durable state behind, so it is sealed even though it\n * leaves the machine.\n *\n * @category effects\n * @since 1.0.0\n */\nexport const effects = envelope({ tier: \"sealed\", mode: \"expected\", reads: [], writes: [] })\n\n/**\n * Narrows the fetch effect envelope for one decoded input.\n *\n * Network reach is expressed as a capability rather than a path envelope, so\n * a retrieval has nothing left to narrow.\n *\n * @category effects\n * @since 1.0.0\n */\nexport const effectsFor = (_input: typeof Input.Type) => effects\n\n/**\n * Capabilities required by the fetch flow.\n *\n * @category capabilities\n * @since 1.0.0\n */\nexport const capabilities = [capability(\"net:get\", \"*\")]\n\n/**\n * Declaration-only fetch flow.\n *\n * @category flows\n * @since 1.0.0\n */\nexport const flow = { name, description, input: Input, output: Output, capabilities, effects } as const\n\n/**\n * Retrieves a URL through the permission-aware kernel HTTP client.\n *\n * Error statuses are ordinary results; only transport, permission, and body\n * decoding failures use the typed error channel.\n *\n * @category handlers\n * @since 1.0.0\n */\nexport const run = Effect.fn(\"Fetch.run\")((input: Input) => execute(input, HttpClientRequest.get))\n"]}
@@ -126,5 +126,5 @@ export declare const run: (input: {
126
126
  readonly body: string;
127
127
  readonly truncated: boolean;
128
128
  readonly notice?: string | undefined;
129
- }, import("./StdError.ts").StdError, import("@smthrs/kernel/GrantStore").GrantStore | import("@smthrs/kernel/HttpClient").HttpClient>;
129
+ }, import("./StdError.ts").StdError, import("@smthrs/kernel/GrantStore").GrantStore | import("effect/http/HttpClient").HttpClient>;
130
130
  //# sourceMappingURL=HttpPost.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"HttpPost.d.ts","sourceRoot":"","sources":["../../src/HttpPost.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AACvC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AAKvC;;;;;GAKG;AACH,eAAO,MAAM,IAAI,cAAc,CAAA;AAE/B;;;;;GAKG;AACH,eAAO,MAAM,WAAW,sIAC6G,CAAA;AAErI;;;;;GAKG;AACH,eAAO,MAAM,KAAK;;;;;;EAYhB,CAAA;AAEF;;;;;GAKG;AACH,MAAM,MAAM,KAAK,GAAG,OAAO,KAAK,CAAC,IAAI,CAAA;AAErC;;;;;GAKG;AACH,eAAO,MAAM,MAAM;;;;;EAAW,CAAA;AAE9B;;;;;GAKG;AACH,MAAM,MAAM,MAAM,GAAG,OAAO,MAAM,CAAC,IAAI,CAAA;AAEvC;;;;;GAKG;AACH,eAAO,MAAM,OAAO,4CAA8E,CAAA;AAElG;;;;;;;;GAQG;AACH,eAAO,MAAM,UAAU,GAAI,QAAQ,OAAO,KAAK,CAAC,IAAI,+CAAY,CAAA;AAEhE;;;;;GAKG;AACH,eAAO,MAAM,YAAY,UAAgC,CAAA;AAEzD;;;;;GAKG;AACH,eAAO,MAAM,IAAI;;;;;;;;;;;;;;;;;;CAAsF,CAAA;AAEvG;;;;;GAKG;AACH,eAAO,MAAM,GAAG;;;;;;;;;;;;;qIAKf,CAAA"}
1
+ {"version":3,"file":"HttpPost.d.ts","sourceRoot":"","sources":["../../src/HttpPost.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AAEvC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AAIvC;;;;;GAKG;AACH,eAAO,MAAM,IAAI,cAAc,CAAA;AAE/B;;;;;GAKG;AACH,eAAO,MAAM,WAAW,sIAC6G,CAAA;AAErI;;;;;GAKG;AACH,eAAO,MAAM,KAAK;;;;;;EAYhB,CAAA;AAEF;;;;;GAKG;AACH,MAAM,MAAM,KAAK,GAAG,OAAO,KAAK,CAAC,IAAI,CAAA;AAErC;;;;;GAKG;AACH,eAAO,MAAM,MAAM;;;;;EAAW,CAAA;AAE9B;;;;;GAKG;AACH,MAAM,MAAM,MAAM,GAAG,OAAO,MAAM,CAAC,IAAI,CAAA;AAEvC;;;;;GAKG;AACH,eAAO,MAAM,OAAO,4CAA8E,CAAA;AAElG;;;;;;;;GAQG;AACH,eAAO,MAAM,UAAU,GAAI,QAAQ,OAAO,KAAK,CAAC,IAAI,+CAAY,CAAA;AAEhE;;;;;GAKG;AACH,eAAO,MAAM,YAAY,UAAgC,CAAA;AAEzD;;;;;GAKG;AACH,eAAO,MAAM,IAAI;;;;;;;;;;;;;;;;;;CAAsF,CAAA;AAEvG;;;;;GAKG;AACH,eAAO,MAAM,GAAG;;;;;;;;;;;;;kIAKf,CAAA"}
@@ -4,8 +4,8 @@
4
4
  * @since 1.0.0
5
5
  */
6
6
  import * as Effect from "effect/Effect";
7
+ import * as HttpClientRequest from "effect/http/HttpClientRequest";
7
8
  import * as Schema from "effect/Schema";
8
- import * as HttpClientRequest from "effect/unstable/http/HttpClientRequest";
9
9
  import { capability, envelope } from "./internal/Declaration.js";
10
10
  import { execute, Response, Timeout } from "./internal/Http.js";
11
11
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"HttpPost.js","sourceRoot":"","sources":["../../src/HttpPost.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AACvC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AACvC,OAAO,KAAK,iBAAiB,MAAM,wCAAwC,CAAA;AAC3E,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAA;AAChE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAA;AAE/D;;;;;GAKG;AACH,MAAM,CAAC,MAAM,IAAI,GAAG,WAAW,CAAA;AAE/B;;;;;GAKG;AACH,MAAM,CAAC,MAAM,WAAW,GACtB,mIAAmI,CAAA;AAErI;;;;;GAKG;AACH,MAAM,CAAC,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC;IACjC,GAAG,EAAE,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,WAAW,EAAE,uCAAuC,EAAE,CAAC;IACrF,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,WAAW,EAAE,4BAA4B,EAAE,CAAC;IAC3E,WAAW,EAAE,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC;QACnD,WAAW,EAAE,oDAAoD;KAClE,CAAC;IACF,OAAO,EAAE,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC;QAC7E,WAAW,EAAE,4BAA4B;KAC1C,CAAC;IACF,OAAO,EAAE,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,QAAQ,CAAC;QACzC,WAAW,EAAE,mFAAmF;KACjG,CAAC;CACH,CAAC,CAAA;AAUF;;;;;GAKG;AACH,MAAM,CAAC,MAAM,MAAM,GAAG,QAAQ,CAAA;AAU9B;;;;;GAKG;AACH,MAAM,CAAC,MAAM,OAAO,GAAG,QAAQ,CAAC,EAAE,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,CAAA;AAElG;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,MAAyB,EAAE,EAAE,CAAC,OAAO,CAAA;AAEhE;;;;;GAKG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,UAAU,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC,CAAA;AAEzD;;;;;GAKG;AACH,MAAM,CAAC,MAAM,IAAI,GAAG,EAAE,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,OAAO,EAAW,CAAA;AAEvG;;;;;GAKG;AACH,MAAM,CAAC,MAAM,GAAG,GAAG,MAAM,CAAC,EAAE,CAAC,cAAc,CAAC,CAAC,CAAC,KAAY,EAAE,EAAE,CAC5D,OAAO,CAAC,KAAK,EAAE,CAAC,GAAG,EAAE,EAAE,CACrB,iBAAiB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAC9B,iBAAiB,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,WAAW,IAAI,kBAAkB,CAAC,CAChF,CAAC,CACL,CAAA","sourcesContent":["/**\n * HTTP POST flow declaration and portable handler.\n *\n * @since 1.0.0\n */\n\nimport * as Effect from \"effect/Effect\"\nimport * as Schema from \"effect/Schema\"\nimport * as HttpClientRequest from \"effect/unstable/http/HttpClientRequest\"\nimport { capability, envelope } from \"./internal/Declaration.ts\"\nimport { execute, Response, Timeout } from \"./internal/Http.ts\"\n\n/**\n * Registry name for the http-post flow.\n *\n * @category identifiers\n * @since 1.0.0\n */\nexport const name = \"http-post\"\n\n/**\n * Model-facing description of the http-post flow.\n *\n * @category descriptions\n * @since 1.0.0\n */\nexport const description =\n \"Post a text body to an absolute URL and return the response; this is irreversible because the remote side may already have acted.\"\n\n/**\n * Input schema for the http-post flow.\n *\n * @category schemas\n * @since 1.0.0\n */\nexport const Input = Schema.Struct({\n url: Schema.String.annotate({ description: \"Absolute http or https URL to post to\" }),\n body: Schema.String.annotate({ description: \"Request body sent verbatim\" }),\n contentType: Schema.optional(Schema.String).annotate({\n description: \"Request content type; defaults to application/json\"\n }),\n headers: Schema.optional(Schema.Record(Schema.String, Schema.String)).annotate({\n description: \"Additional request headers\"\n }),\n timeout: Schema.optional(Timeout).annotate({\n description: \"Total request and response body timeout in seconds; defaults to 30, capped at 120\"\n })\n})\n\n/**\n * Decoded input accepted by the `http-post` flow.\n *\n * @category models\n * @since 1.0.0\n */\nexport type Input = typeof Input.Type\n\n/**\n * Output schema for the http-post flow.\n *\n * @category schemas\n * @since 1.0.0\n */\nexport const Output = Response\n\n/**\n * Decoded output returned by the `http-post` flow.\n *\n * @category models\n * @since 1.0.0\n */\nexport type Output = typeof Output.Type\n\n/**\n * Static effect envelope for the http-post flow.\n *\n * @category effects\n * @since 1.0.0\n */\nexport const effects = envelope({ tier: \"irreversible\", mode: \"expected\", reads: [], writes: [] })\n\n/**\n * Narrows the http-post effect envelope for one decoded input.\n *\n * Network reach is expressed as a capability rather than a path envelope, so\n * a post has nothing left to narrow.\n *\n * @category effects\n * @since 1.0.0\n */\nexport const effectsFor = (_input: typeof Input.Type) => effects\n\n/**\n * Capabilities required by the http-post flow.\n *\n * @category capabilities\n * @since 1.0.0\n */\nexport const capabilities = [capability(\"net:post\", \"*\")]\n\n/**\n * Declaration-only http-post flow.\n *\n * @category flows\n * @since 1.0.0\n */\nexport const flow = { name, description, input: Input, output: Output, capabilities, effects } as const\n\n/**\n * Posts a body through the permission-aware kernel HTTP client.\n *\n * @category handlers\n * @since 1.0.0\n */\nexport const run = Effect.fn(\"HttpPost.run\")((input: Input) =>\n execute(input, (url) =>\n HttpClientRequest.post(url).pipe(\n HttpClientRequest.bodyText(input.body, input.contentType ?? \"application/json\")\n ))\n)\n"]}
1
+ {"version":3,"file":"HttpPost.js","sourceRoot":"","sources":["../../src/HttpPost.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AACvC,OAAO,KAAK,iBAAiB,MAAM,+BAA+B,CAAA;AAClE,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AACvC,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAA;AAChE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAA;AAE/D;;;;;GAKG;AACH,MAAM,CAAC,MAAM,IAAI,GAAG,WAAW,CAAA;AAE/B;;;;;GAKG;AACH,MAAM,CAAC,MAAM,WAAW,GACtB,mIAAmI,CAAA;AAErI;;;;;GAKG;AACH,MAAM,CAAC,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC;IACjC,GAAG,EAAE,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,WAAW,EAAE,uCAAuC,EAAE,CAAC;IACrF,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,WAAW,EAAE,4BAA4B,EAAE,CAAC;IAC3E,WAAW,EAAE,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC;QACnD,WAAW,EAAE,oDAAoD;KAClE,CAAC;IACF,OAAO,EAAE,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC;QAC7E,WAAW,EAAE,4BAA4B;KAC1C,CAAC;IACF,OAAO,EAAE,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,QAAQ,CAAC;QACzC,WAAW,EAAE,mFAAmF;KACjG,CAAC;CACH,CAAC,CAAA;AAUF;;;;;GAKG;AACH,MAAM,CAAC,MAAM,MAAM,GAAG,QAAQ,CAAA;AAU9B;;;;;GAKG;AACH,MAAM,CAAC,MAAM,OAAO,GAAG,QAAQ,CAAC,EAAE,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,CAAA;AAElG;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,MAAyB,EAAE,EAAE,CAAC,OAAO,CAAA;AAEhE;;;;;GAKG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,UAAU,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC,CAAA;AAEzD;;;;;GAKG;AACH,MAAM,CAAC,MAAM,IAAI,GAAG,EAAE,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,OAAO,EAAW,CAAA;AAEvG;;;;;GAKG;AACH,MAAM,CAAC,MAAM,GAAG,GAAG,MAAM,CAAC,EAAE,CAAC,cAAc,CAAC,CAAC,CAAC,KAAY,EAAE,EAAE,CAC5D,OAAO,CAAC,KAAK,EAAE,CAAC,GAAG,EAAE,EAAE,CACrB,iBAAiB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAC9B,iBAAiB,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,WAAW,IAAI,kBAAkB,CAAC,CAChF,CAAC,CACL,CAAA","sourcesContent":["/**\n * HTTP POST flow declaration and portable handler.\n *\n * @since 1.0.0\n */\n\nimport * as Effect from \"effect/Effect\"\nimport * as HttpClientRequest from \"effect/http/HttpClientRequest\"\nimport * as Schema from \"effect/Schema\"\nimport { capability, envelope } from \"./internal/Declaration.ts\"\nimport { execute, Response, Timeout } from \"./internal/Http.ts\"\n\n/**\n * Registry name for the http-post flow.\n *\n * @category identifiers\n * @since 1.0.0\n */\nexport const name = \"http-post\"\n\n/**\n * Model-facing description of the http-post flow.\n *\n * @category descriptions\n * @since 1.0.0\n */\nexport const description =\n \"Post a text body to an absolute URL and return the response; this is irreversible because the remote side may already have acted.\"\n\n/**\n * Input schema for the http-post flow.\n *\n * @category schemas\n * @since 1.0.0\n */\nexport const Input = Schema.Struct({\n url: Schema.String.annotate({ description: \"Absolute http or https URL to post to\" }),\n body: Schema.String.annotate({ description: \"Request body sent verbatim\" }),\n contentType: Schema.optional(Schema.String).annotate({\n description: \"Request content type; defaults to application/json\"\n }),\n headers: Schema.optional(Schema.Record(Schema.String, Schema.String)).annotate({\n description: \"Additional request headers\"\n }),\n timeout: Schema.optional(Timeout).annotate({\n description: \"Total request and response body timeout in seconds; defaults to 30, capped at 120\"\n })\n})\n\n/**\n * Decoded input accepted by the `http-post` flow.\n *\n * @category models\n * @since 1.0.0\n */\nexport type Input = typeof Input.Type\n\n/**\n * Output schema for the http-post flow.\n *\n * @category schemas\n * @since 1.0.0\n */\nexport const Output = Response\n\n/**\n * Decoded output returned by the `http-post` flow.\n *\n * @category models\n * @since 1.0.0\n */\nexport type Output = typeof Output.Type\n\n/**\n * Static effect envelope for the http-post flow.\n *\n * @category effects\n * @since 1.0.0\n */\nexport const effects = envelope({ tier: \"irreversible\", mode: \"expected\", reads: [], writes: [] })\n\n/**\n * Narrows the http-post effect envelope for one decoded input.\n *\n * Network reach is expressed as a capability rather than a path envelope, so\n * a post has nothing left to narrow.\n *\n * @category effects\n * @since 1.0.0\n */\nexport const effectsFor = (_input: typeof Input.Type) => effects\n\n/**\n * Capabilities required by the http-post flow.\n *\n * @category capabilities\n * @since 1.0.0\n */\nexport const capabilities = [capability(\"net:post\", \"*\")]\n\n/**\n * Declaration-only http-post flow.\n *\n * @category flows\n * @since 1.0.0\n */\nexport const flow = { name, description, input: Input, output: Output, capabilities, effects } as const\n\n/**\n * Posts a body through the permission-aware kernel HTTP client.\n *\n * @category handlers\n * @since 1.0.0\n */\nexport const run = Effect.fn(\"HttpPost.run\")((input: Input) =>\n execute(input, (url) =>\n HttpClientRequest.post(url).pipe(\n HttpClientRequest.bodyText(input.body, input.contentType ?? \"application/json\")\n ))\n)\n"]}
package/dist/esm/Lsp.d.ts CHANGED
@@ -114,7 +114,7 @@ export declare const flow: {
114
114
  * @since 1.0.0
115
115
  */
116
116
  export declare const run: (input: {
117
- readonly operation: "hover" | "definition" | "references" | "implementation" | "documentSymbols" | "workspaceSymbols" | "prepareCallHierarchy" | "callHierarchyIncoming" | "callHierarchyOutgoing" | "diagnostics";
117
+ readonly operation: "references" | "hover" | "definition" | "implementation" | "documentSymbols" | "workspaceSymbols" | "prepareCallHierarchy" | "callHierarchyIncoming" | "callHierarchyOutgoing" | "diagnostics";
118
118
  readonly path?: string | undefined;
119
119
  readonly line?: number | undefined;
120
120
  readonly character?: number | undefined;