acrylblends 1.0.3 → 1.0.5
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.
- package/docs/framework/agents/index.md +6 -4
- package/docs/framework/workshop/README.md +3 -3
- package/docs/framework/workshop/facilitator.md +1 -0
- package/lib/accept-CNNHu4Cf.js +193 -0
- package/lib/{accepts-XBuZPVRI.js → accepts-Btq83xPd.js} +1 -1
- package/lib/accepts.js +1 -1
- package/lib/acryl-base.js +1 -331
- package/lib/adapter-CaZ6FZUU.js +37 -0
- package/lib/adapter.js +1 -36
- package/lib/{app-BM0rTCp7.js → app-CQcGWjrk.js} +4 -4
- package/lib/app-base-CpRMZL4v.js +332 -0
- package/lib/{audit-BXnYsLge.d.ts → audit-D5z9uwOP.d.ts} +14 -1
- package/lib/{base-NSN_SNv-.js → base-D_6kfOr-.js} +1 -1
- package/lib/basic-auth-C0HTRpXh.js +20 -0
- package/lib/basic-auth-DFLflXNe.js +95 -0
- package/lib/basic-auth.js +1 -94
- package/lib/bearer-auth-Cwxt-vgS.js +94 -0
- package/lib/bearer-auth.js +1 -93
- package/lib/body-D7f4e7w_.js +94 -0
- package/lib/body-limit-WmIjWRLt.js +66 -0
- package/lib/body-limit.js +1 -65
- package/lib/buffer-CkEOJCcY.js +51 -0
- package/lib/bun.js +3 -3
- package/lib/cache-B0bHH7s5.js +169 -0
- package/lib/cache.js +1 -168
- package/lib/{client-DDLXwhBo.js → client-BrMFnMEd.js} +1 -1
- package/lib/{client-modules-CLvWOjbd.js → client-modules-drj4mjhj.js} +4 -4
- package/lib/client.js +1 -1
- package/lib/color-COa3DplO.js +37 -0
- package/lib/combine-TWuGdcbC.js +137 -0
- package/lib/combine.js +1 -136
- package/lib/{components-cEW3ovK0.js → components-B2ka9Ax1.js} +4 -4
- package/lib/{components-JXVm45kK.js → components-PVXwaOaC.js} +2 -2
- package/lib/compress-BzWqsHF1.js +79 -0
- package/lib/compress-C-9vK4B2.d.ts +11 -0
- package/lib/compress-DCyrrQ5D.js +11 -0
- package/lib/compress.d.ts +1 -1
- package/lib/compress.js +2 -78
- package/lib/concurrent-DrF3d2c-.js +30 -0
- package/lib/conninfo-BCROmdnf.d.ts +11 -0
- package/lib/conninfo-CWJwieh4.js +19 -0
- package/lib/constants-CBSEudrb.js +7 -0
- package/lib/{context-DDO0cfuP.js → context-CkOh7Ygv.js} +2 -2
- package/lib/context-storage-iuPoI_CR.js +52 -0
- package/lib/context-storage.js +1 -51
- package/lib/cookie-B1LlkzOe.js +125 -0
- package/lib/cookie-BHIduy2T.js +82 -0
- package/lib/cookie.js +1 -81
- package/lib/cordis/db-sqlite.d.ts +1 -1
- package/lib/cordis/door.d.ts +17 -3
- package/lib/cordis/door.js +123 -16
- package/lib/cordis/inspect.js +4 -4
- package/lib/cordis/kv-db.d.ts +1 -1
- package/lib/cordis/kv-db.js +1 -1
- package/lib/cordis/kv-json.d.ts +1 -1
- package/lib/cordis/kv-json.js +1 -1
- package/lib/cordis/node-server.d.ts +1 -1
- package/lib/cordis/node-server.js +3 -116
- package/lib/cordis/router-http.d.ts +1 -1
- package/lib/cordis/router-http.js +2 -2
- package/lib/cordis/router.d.ts +1 -1
- package/lib/cordis/router.js +4 -4
- package/lib/cordis/state.js +7 -7
- package/lib/{core-CaY8XDZ6.js → core-BOu1jYua.js} +1 -1
- package/lib/cors-CbAQ-8qU.js +106 -0
- package/lib/cors.js +1 -105
- package/lib/crypto-iVP-N-tS.js +34 -0
- package/lib/csrf-DqqOZtgy.js +101 -0
- package/lib/csrf.js +1 -100
- package/lib/css-C5CPVMvM.js +134 -0
- package/lib/css.js +2 -133
- package/lib/db/sqlite.d.ts +1 -25
- package/lib/dev-CLgu-JRe.js +50 -0
- package/lib/dev.js +1 -49
- package/lib/dom-YjND9Jt3.js +74 -0
- package/lib/door/host.d.ts +2 -2
- package/lib/door/host.js +1 -1
- package/lib/door/page.d.ts +12 -1
- package/lib/door/page.js +22 -1
- package/lib/door/protocol.d.ts +2 -2
- package/lib/door/protocol.js +2 -197
- package/lib/encode-BhbNLrjp.js +33 -0
- package/lib/factory-CLdSf-xS.js +30 -0
- package/lib/factory.js +1 -29
- package/lib/handler-C0wZ0KwO.js +12 -0
- package/lib/helpers-BEjcdbgw.js +5 -0
- package/lib/{hooks-w72iLeFR.js → hooks-CfC07ri0.js} +1 -1
- package/lib/html-CgNa89xw.js +31 -0
- package/lib/html-DGExBFNg.js +103 -0
- package/lib/html.d.ts +2 -5
- package/lib/html.js +2 -30
- package/lib/http-exception-MjWkT89V.js +54 -0
- package/lib/http-exception.js +1 -53
- package/lib/{index-D4nVR3wu.d.ts → index-DMOtA-NJ.d.ts} +7 -1
- package/lib/index-dAzQsJG9.d.ts +6 -0
- package/lib/index.js +3 -3
- package/lib/ip-restriction-jKtKCRM_.js +166 -0
- package/lib/ip-restriction.js +1 -165
- package/lib/ipaddr-DCoIo528.js +238 -0
- package/lib/jsx/dom/client.js +1 -1
- package/lib/jsx/dom/jsx-dev-runtime.js +1 -1
- package/lib/jsx/dom/jsx-runtime.js +2 -1
- package/lib/jsx/dom/server.js +3 -3
- package/lib/jsx/dom.js +5 -73
- package/lib/jsx/jsx-dev-runtime.d.ts +2 -5
- package/lib/jsx/jsx-dev-runtime.js +2 -13
- package/lib/jsx/jsx-runtime.d.ts +2 -2
- package/lib/jsx/jsx-runtime.js +4 -4
- package/lib/jsx/streaming.js +1 -1
- package/lib/jsx-CUQgttxU.js +47 -0
- package/lib/jsx-dev-runtime-B4WTyq8r.js +14 -0
- package/lib/{jsx-dev-runtime-CWLRA2F3.js → jsx-dev-runtime-BLfA-EhI.js} +2 -2
- package/lib/jsx-dev-runtime-CGt4kNYr.d.ts +6 -0
- package/lib/jsx-renderer-CfifM4hT.js +99 -0
- package/lib/jsx-renderer.js +1 -98
- package/lib/jsx-runtime-COCRWBJ9.js +2 -0
- package/lib/jsx.js +5 -46
- package/lib/{jwk-LkzeoaU8.js → jwk-CDPpYQpD.js} +3 -3
- package/lib/jwk.js +1 -1
- package/lib/{jwt-BGJBw5AF.js → jwt-BXoIA2fQ.js} +2 -2
- package/lib/{jwt-CskdhEW9.js → jwt-lyS4Q3mT.js} +3 -3
- package/lib/jwt.js +2 -2
- package/lib/kv/db.d.ts +1 -10
- package/lib/kv/db.js +1 -56
- package/lib/kv/json.d.ts +1 -9
- package/lib/kv/json.js +1 -223
- package/lib/{language-D9a4zqvn.js → language-DeGRtLJt.js} +2 -2
- package/lib/language.js +1 -1
- package/lib/{linear-router-C3FPib6h.js → linear-router-CmZn_JLV.js} +2 -2
- package/lib/logger-Ckxu8diz.js +54 -0
- package/lib/logger.js +1 -53
- package/lib/loopback-only-BbasoF7R.js +90 -0
- package/lib/loopback-only.js +1 -89
- package/lib/method-not-allowed-TO2_hnfl.js +82 -0
- package/lib/method-not-allowed.js +1 -81
- package/lib/method-override-DnZKfJbV.js +103 -0
- package/lib/method-override.js +1 -102
- package/lib/middleware-BfG_fp8P.js +12 -0
- package/lib/mime-BnScXkQn.js +77 -0
- package/lib/mount-QkK_3NtJ.js +67 -0
- package/lib/mount.js +1 -66
- package/lib/node-server/conninfo.d.ts +1 -10
- package/lib/node-server/conninfo.js +1 -18
- package/lib/node-server/register.js +25 -2
- package/lib/node-server/serve-static.d.ts +1 -17
- package/lib/node-server/serve-static.js +1 -1
- package/lib/node-server.d.ts +2 -2
- package/lib/node-server.js +4 -4
- package/lib/open-BqK4D2Wn.d.ts +11 -0
- package/lib/open-But9E2rL.js +57 -0
- package/lib/open-CULVJgOc.d.ts +12 -0
- package/lib/open-Dp4sxspc.js +224 -0
- package/lib/open-T7kgbO2O.d.ts +27 -0
- package/lib/{pattern-router-HZxjDGEQ.js → pattern-router-CJBecJBd.js} +1 -1
- package/lib/powered-by-CXQNjNIX.js +24 -0
- package/lib/powered-by.js +1 -23
- package/lib/pretty-json-CeC1yvYt.js +39 -0
- package/lib/pretty-json.js +1 -38
- package/lib/{protocol-BizVt4J6.d.ts → protocol-C37gPePD.d.ts} +9 -2
- package/lib/protocol-Dt0AZBOz.js +213 -0
- package/lib/proxy-C2w_mH7k.js +121 -0
- package/lib/proxy.js +1 -120
- package/lib/quick.js +4 -4
- package/lib/{reg-exp-router-DC1R3qoY.js → reg-exp-router-C_WV84eV.js} +2 -2
- package/lib/request-DvMgGtlW.js +323 -0
- package/lib/request.js +1 -322
- package/lib/route-D8m-a2I1.js +126 -0
- package/lib/route.js +1 -125
- package/lib/router/linear-router.js +1 -1
- package/lib/router/pattern-router.js +1 -1
- package/lib/router/reg-exp-router.js +1 -1
- package/lib/router/smart-router.js +1 -1
- package/lib/router/trie-router.js +1 -1
- package/lib/router-Be_o6nFu.js +35 -0
- package/lib/router.js +1 -34
- package/lib/schema-validator-EK3cUUCt.js +22 -0
- package/lib/schema-validator.js +1 -21
- package/lib/{secure-headers-mP3j6Hm6.js → secure-headers-C5ZOcXqk.js} +1 -1
- package/lib/secure-headers.js +1 -1
- package/lib/serve-static-B7sqnftW.d.ts +18 -0
- package/lib/{serve-static-3uo_9rjF.js → serve-static-C1Nkj_xB.js} +2 -2
- package/lib/{serve-static-Cp5adzGo.js → serve-static-EiJf1zkO.js} +4 -4
- package/lib/serve-static.js +1 -1
- package/lib/{smart-router-C5CZ5XSM.js → smart-router-BjxkDQCE.js} +1 -1
- package/lib/{snapshot-text-DmE0YfeZ.js → snapshot-text-Bbx43mN0.js} +57 -9
- package/lib/{src-2Z4mJg0x.js → src-BTBm4OPD.js} +22 -6
- package/lib/src-LX0E4ec4.js +117 -0
- package/lib/{ssg-BwjcA-Ge.js → ssg-BEl7MHqg.js} +5 -5
- package/lib/ssg.js +1 -1
- package/lib/stream-CzM_SHkq.js +88 -0
- package/lib/{streaming-DHST3Scg.js → streaming-BlDaph8U.js} +3 -3
- package/lib/streaming.js +1 -1
- package/lib/{test-websocket-D8WWqE5G.js → test-websocket-BLeEvybj.js} +2 -2
- package/lib/testing-BQx5T_UX.js +17 -0
- package/lib/testing.js +1 -16
- package/lib/timeout-FeqZ9A-0.js +42 -0
- package/lib/timeout.js +1 -41
- package/lib/tiny.js +2 -2
- package/lib/trailing-slash-DwTx-1sk.js +85 -0
- package/lib/trailing-slash.js +1 -84
- package/lib/{trie-router-CfFbapzL.js → trie-router-JydLKUa2.js} +2 -2
- package/lib/url-BPh4d6j-.js +197 -0
- package/lib/utils/accept.js +1 -192
- package/lib/utils/basic-auth.js +1 -19
- package/lib/utils/body.js +1 -93
- package/lib/utils/buffer.js +1 -50
- package/lib/utils/color.js +1 -36
- package/lib/utils/compress.d.ts +1 -10
- package/lib/utils/compress.js +1 -10
- package/lib/utils/concurrent.js +1 -29
- package/lib/utils/constants.js +1 -6
- package/lib/utils/cookie.js +1 -124
- package/lib/utils/crypto.js +1 -33
- package/lib/utils/encode.js +1 -32
- package/lib/utils/handler.js +1 -11
- package/lib/utils/html.js +1 -102
- package/lib/utils/ipaddr.js +1 -237
- package/lib/utils/jwt.js +1 -1
- package/lib/utils/mime.js +1 -76
- package/lib/utils/stream.js +1 -87
- package/lib/utils/url.js +1 -196
- package/lib/{validator-D84mq-dO.js → validator-Btiyt5VJ.js} +3 -3
- package/lib/validator.js +1 -1
- package/lib/websocket-DsyBIKVA.js +56 -0
- package/lib/ws.js +1 -55
- package/package.json +1 -1
- package/plugins/acryl-door/src/cli/acryl.ts +5 -3
- package/plugins/acryl-door/src/host/channel.ts +36 -0
- package/plugins/acryl-door/src/host/chat-tools.ts +2 -0
- package/plugins/acryl-door/src/host/door.ts +44 -5
- package/plugins/acryl-door/src/host/shim.ts +23 -0
- package/plugins/acryl-door/src/host/verbs.ts +4 -3
- package/plugins/acryl-door/src/index.ts +39 -3
- package/plugins/acryl-door/src/page/driver/driver.ts +22 -1
- package/plugins/acryl-door/src/page/protocol.ts +13 -2
- package/plugins/acryl-node-server/src/register.ts +29 -2
- package/plugins/acryl-router/src/service.ts +19 -1
- package/plugins/agent/model.ts +6 -1
- package/plugins/agent/tools.ts +12 -2
- package/plugins/agent-panel/client/describe.ts +44 -0
- package/plugins/agent-panel/client/main.ts +67 -35
- package/plugins/agent-panel/index.ts +137 -35
- package/plugins/desktop/attach.ts +72 -0
- package/plugins/desktop/main.ts +17 -4
- package/plugins/extensions/index.ts +3 -4
- package/plugins/extensions/stage.ts +33 -5
- package/plugins/openai/index.ts +1 -1
- package/shared/DEFAULTS.md +4 -0
- package/templates/agent/AGENTS.md +2 -0
- package/templates/agent/blend.yaml +4 -1
- package/templates/agent/src/app.ts +2 -0
- package/templates/agent/src/routes.ts +1 -1
- package/templates/agent/template.json +1 -0
- package/templates/agent/test/builder.test.ts +26 -21
- package/lib/helpers-CvTauQT5.js +0 -5
- package/lib/middleware-CPQ8himN.js +0 -12
package/lib/cordis/door.js
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
|
-
import { t as Acryl } from "../app-
|
|
2
|
-
import { n as clientModules } from "../client-modules-
|
|
3
|
-
import {
|
|
4
|
-
import { a as INVALID_JSON, c as operatorOnly, d as AuditLog, f as auditPath, i as DOOR_PREFIX, l as privateApi, o as error, p as UiChannel, r as pageChannelRoutes, s as jsonBody, t as renderSnapshot, u as readJson } from "../snapshot-text-
|
|
5
|
-
import "../src-
|
|
1
|
+
import { t as Acryl } from "../app-CQcGWjrk.js";
|
|
2
|
+
import { n as clientModules } from "../client-modules-drj4mjhj.js";
|
|
3
|
+
import { a as MAX_WAIT_MS, l as UiControlError, p as parseUiRequest, r as MAX_SNAPSHOT_NODES } from "../protocol-Dt0AZBOz.js";
|
|
4
|
+
import { a as INVALID_JSON, c as operatorOnly, d as AuditLog, f as auditPath, i as DOOR_PREFIX, l as privateApi, o as error, p as UiChannel, r as pageChannelRoutes, s as jsonBody, t as renderSnapshot, u as readJson } from "../snapshot-text-Bbx43mN0.js";
|
|
5
|
+
import "../src-BTBm4OPD.js";
|
|
6
6
|
import { isAbsolute, join, relative, resolve } from "node:path";
|
|
7
7
|
import { chmodSync, existsSync, mkdirSync, readFileSync, renameSync, rmSync, writeFileSync } from "node:fs";
|
|
8
8
|
import z from "@deepseek-ai/schemastery";
|
|
9
9
|
import { randomBytes } from "node:crypto";
|
|
10
|
+
import { spawnSync } from "node:child_process";
|
|
10
11
|
//#region ../../plugins/acryl-door/src/host/verbs.ts
|
|
11
12
|
/**
|
|
12
13
|
* The one verb list (spec 049 slice 13). Every face of the door reads it: the operator client (`acryl <verb>`, its `verbs` and `brief`),
|
|
@@ -56,8 +57,8 @@ const VERB_SPECS = {
|
|
|
56
57
|
}
|
|
57
58
|
},
|
|
58
59
|
"act": {
|
|
59
|
-
usage: "act click|type|select|press|scroll|wait ...: do one thing on the page (refs from the latest look)",
|
|
60
|
-
description: "Do one thing on the page: click, type, select, press a key, scroll,
|
|
60
|
+
usage: "act click|type|select|press|scroll|wait|reload|navigate ...: do one thing on the page (refs from the latest look)",
|
|
61
|
+
description: "Do one thing on the page: click, type, select, press a key, scroll, wait for text or a control, reload the page, or navigate to another path of the app. Look again before the next act.",
|
|
61
62
|
arguments: {
|
|
62
63
|
type: "object",
|
|
63
64
|
properties: {
|
|
@@ -69,9 +70,15 @@ const VERB_SPECS = {
|
|
|
69
70
|
"select",
|
|
70
71
|
"press",
|
|
71
72
|
"scroll",
|
|
72
|
-
"wait"
|
|
73
|
+
"wait",
|
|
74
|
+
"reload",
|
|
75
|
+
"navigate"
|
|
73
76
|
]
|
|
74
77
|
},
|
|
78
|
+
path: {
|
|
79
|
+
type: "string",
|
|
80
|
+
description: "navigate: a path of this app, e.g. /demo (the page must load the door script to be controlled afterwards)"
|
|
81
|
+
},
|
|
75
82
|
ref: {
|
|
76
83
|
type: "string",
|
|
77
84
|
description: "a ref from the latest look, e.g. 3.12"
|
|
@@ -211,6 +218,8 @@ const SELF_KNOWLEDGE = [
|
|
|
211
218
|
"docs",
|
|
212
219
|
"plugins"
|
|
213
220
|
];
|
|
221
|
+
/** How long a reload or a move may take before the new page has connected to the door again. */
|
|
222
|
+
const PAGE_BACK_MS = 15e3;
|
|
214
223
|
var Door = class {
|
|
215
224
|
deps;
|
|
216
225
|
constructor(deps) {
|
|
@@ -235,7 +244,7 @@ var Door = class {
|
|
|
235
244
|
text: `done${result.target === void 0 ? "" : `: ${result.target.role} "${result.target.name}"`}${result.detail === void 0 ? "" : ` (${result.detail})`}; look again before the next act`
|
|
236
245
|
};
|
|
237
246
|
}
|
|
238
|
-
case "plugin-list": return this.plugin((extensions) => extensions.list());
|
|
247
|
+
case "plugin-list": return this.plugin((extensions) => extensions.list(), false);
|
|
239
248
|
case "plugin-add": return this.plugin((extensions) => extensions.install(this.insideApp(input.folder)));
|
|
240
249
|
case "plugin-remove": {
|
|
241
250
|
const name = input.name;
|
|
@@ -286,9 +295,45 @@ var Door = class {
|
|
|
286
295
|
});
|
|
287
296
|
return this.callPage("look", request, signal);
|
|
288
297
|
}
|
|
289
|
-
act(input, signal) {
|
|
298
|
+
async act(input, signal) {
|
|
290
299
|
if (input.op === "snapshot") throw new DoorError("invalid", "use look to see the page");
|
|
291
|
-
|
|
300
|
+
const request = this.parse(input);
|
|
301
|
+
if (request.op !== "reload" && request.op !== "navigate") return await this.callPage(`act ${String(input.op)}`, request, signal);
|
|
302
|
+
const back = this.deps.channel.expectAttach(this.deps.pageBackMs ?? PAGE_BACK_MS);
|
|
303
|
+
let answer;
|
|
304
|
+
try {
|
|
305
|
+
answer = await this.callPage(`act ${request.op}`, request, signal);
|
|
306
|
+
} catch (cause) {
|
|
307
|
+
if (!(cause instanceof UiControlError && cause.code === "disconnected")) throw cause;
|
|
308
|
+
answer = {
|
|
309
|
+
ok: true,
|
|
310
|
+
detail: request.op === "reload" ? "reloading" : `going to ${request.path}`
|
|
311
|
+
};
|
|
312
|
+
}
|
|
313
|
+
if (!await back) throw new UiControlError("timeout", request.op === "reload" ? "the page did not come back after the reload" : `the page did not come back after going to ${request.path}: is there a page at that path, and does it load the door's script?`);
|
|
314
|
+
const landed = request.op === "navigate" ? await this.statusAt(request.path) : void 0;
|
|
315
|
+
return {
|
|
316
|
+
...answer,
|
|
317
|
+
detail: `${answer.detail ?? "done"}${landed === void 0 ? "" : `; ${landed}`}; the page is back: look again`
|
|
318
|
+
};
|
|
319
|
+
}
|
|
320
|
+
/**
|
|
321
|
+
* What the app answers at a path the page was sent to, so an agent that mistyped one is told ("404 at /nope") and not left to find out from a page it did not expect.
|
|
322
|
+
* A second GET of the same path (a page is read-only); nothing when the app has no address or does not answer in time.
|
|
323
|
+
*/
|
|
324
|
+
async statusAt(path) {
|
|
325
|
+
const base = this.deps.app.url;
|
|
326
|
+
if (base === void 0) return void 0;
|
|
327
|
+
try {
|
|
328
|
+
const response = await fetch(new URL(path, base), {
|
|
329
|
+
headers: { accept: "text/html" },
|
|
330
|
+
signal: AbortSignal.timeout(3e3)
|
|
331
|
+
});
|
|
332
|
+
await response.body?.cancel();
|
|
333
|
+
return response.ok ? `${response.status} at ${path}` : `${response.status} at ${path}: the app serves no page there, look at what is shown and navigate to a path it does`;
|
|
334
|
+
} catch {
|
|
335
|
+
return;
|
|
336
|
+
}
|
|
292
337
|
}
|
|
293
338
|
parse(input) {
|
|
294
339
|
try {
|
|
@@ -335,10 +380,12 @@ var Door = class {
|
|
|
335
380
|
throw cause;
|
|
336
381
|
}
|
|
337
382
|
}
|
|
338
|
-
async plugin(run) {
|
|
383
|
+
async plugin(run, mutates = true) {
|
|
339
384
|
const extensions = this.deps.extensions();
|
|
340
385
|
if (extensions === void 0) throw new DoorError("unavailable", "this app has no extensions plugin, so plugins cannot be installed while it runs");
|
|
341
386
|
const value = await run(extensions);
|
|
387
|
+
const unchanged = typeof value === "object" && value !== null && value.action === "unchanged";
|
|
388
|
+
if (mutates && !unchanged && this.deps.reloadOnChange !== false) await this.deps.channel.reloadAll();
|
|
342
389
|
return {
|
|
343
390
|
value,
|
|
344
391
|
text: JSON.stringify(value, null, 2)
|
|
@@ -398,6 +445,7 @@ function registerChatTools(tools, door) {
|
|
|
398
445
|
try {
|
|
399
446
|
for (const verb of VERBS) removers.push(tools.register(chatToolName(verb), {
|
|
400
447
|
description: VERB_SPECS[verb].description,
|
|
448
|
+
parameters: VERB_SPECS[verb].arguments,
|
|
401
449
|
run: async (input) => {
|
|
402
450
|
try {
|
|
403
451
|
return (await door.run(verb, input ?? {}, running.signal)).text;
|
|
@@ -631,6 +679,34 @@ function operatorRoutes(prefix, secret, door, reportError) {
|
|
|
631
679
|
}
|
|
632
680
|
});
|
|
633
681
|
}
|
|
682
|
+
/** The oldest Node the client runs on (the framework's own floor). */
|
|
683
|
+
const MIN_NODE = [22, 19];
|
|
684
|
+
/**
|
|
685
|
+
* A real Node for the command, when the app runs inside Electron: Electron can run the client as Node, but on macOS every such call prints a code-signing complaint on stderr,
|
|
686
|
+
* which lands in an agent's transcript. A `node` on the PATH that is new enough is used instead; without one, Electron runs the client. `find` is replaceable for tests.
|
|
687
|
+
*/
|
|
688
|
+
function realNode(find = findNodeOnPath) {
|
|
689
|
+
const found = find();
|
|
690
|
+
if (found === void 0) return void 0;
|
|
691
|
+
const [major = 0, minor = 0] = found.version.replace(/^v/u, "").split(".").map(Number);
|
|
692
|
+
return major > MIN_NODE[0] || major === MIN_NODE[0] && minor >= MIN_NODE[1] ? found.path : void 0;
|
|
693
|
+
}
|
|
694
|
+
function findNodeOnPath() {
|
|
695
|
+
const located = spawnSync(process.platform === "win32" ? "where" : "which", ["node"], {
|
|
696
|
+
encoding: "utf8",
|
|
697
|
+
env: {
|
|
698
|
+
...process.env,
|
|
699
|
+
ELECTRON_RUN_AS_NODE: void 0
|
|
700
|
+
}
|
|
701
|
+
});
|
|
702
|
+
const path = located.status === 0 ? located.stdout.split(/\r?\n/u).find((line) => line.trim() !== "")?.trim() : void 0;
|
|
703
|
+
if (path === void 0) return void 0;
|
|
704
|
+
const asked = spawnSync(path, ["--version"], { encoding: "utf8" });
|
|
705
|
+
return asked.status === 0 ? {
|
|
706
|
+
path,
|
|
707
|
+
version: asked.stdout.trim()
|
|
708
|
+
} : void 0;
|
|
709
|
+
}
|
|
634
710
|
/** A word for `sh`: single-quoted, with each `'` closed, escaped and reopened. */
|
|
635
711
|
function shWord(value) {
|
|
636
712
|
return `'${value.replaceAll("'", "'\\''")}'`;
|
|
@@ -698,6 +774,7 @@ const inject = [
|
|
|
698
774
|
];
|
|
699
775
|
const Config = z.object({
|
|
700
776
|
allowInProduction: z.boolean().default(false).description("Run in production too (NODE_ENV=production); ACRYL_DOOR=off still turns it off."),
|
|
777
|
+
reloadOnChange: z.boolean().default(true).description("Reload the open pages after a plugin was added, removed or reloaded while the app runs."),
|
|
701
778
|
tools: z.object({ expose: z.array(z.string().pattern(/^(?!door_)[A-Za-z][A-Za-z0-9_-]{0,63}$/u)).description("App tools (from the tools registry) the door offers; none by default.") })
|
|
702
779
|
});
|
|
703
780
|
/** The page module, served compiled from source by the app's own TypeScript. */
|
|
@@ -707,11 +784,13 @@ const CLIENT = import.meta.url.endsWith(".ts") ? join(import.meta.dirname, "cli"
|
|
|
707
784
|
/** How the folder's `.acryl/bin/acryl` starts the client: with the Node that runs the app, and its type-stripping flag when run from source. */
|
|
708
785
|
function shimTarget() {
|
|
709
786
|
const fromSource = CLIENT.endsWith(".ts");
|
|
787
|
+
const inElectron = process.versions.electron !== void 0;
|
|
788
|
+
const node = inElectron ? realNode() : void 0;
|
|
710
789
|
return {
|
|
711
|
-
node: process.execPath,
|
|
790
|
+
node: node ?? process.execPath,
|
|
712
791
|
nodeOptions: fromSource ? process.execArgv.filter((option) => /^--experimental-(strip|transform)-types$/u.test(option)) : [],
|
|
713
792
|
client: CLIENT,
|
|
714
|
-
electron:
|
|
793
|
+
electron: inElectron && node === void 0
|
|
715
794
|
};
|
|
716
795
|
}
|
|
717
796
|
/** A listening address as one the operator reaches: an any-address bind is reached on loopback. */
|
|
@@ -720,6 +799,11 @@ function loopbackUrl(url) {
|
|
|
720
799
|
if (parsed.hostname === "0.0.0.0" || parsed.hostname === "[::]") parsed.hostname = "127.0.0.1";
|
|
721
800
|
return parsed.origin;
|
|
722
801
|
}
|
|
802
|
+
const escapeHtml = (text) => text.replace(/[&<>"']/gu, (char) => `&#${char.charCodeAt(0)};`);
|
|
803
|
+
/** The page of a path the app does not serve, development only: what is missing, a way back, and the door's script. */
|
|
804
|
+
function notFoundPage(path, scriptTag) {
|
|
805
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8"><title>404 Not Found</title></head><body><main><h1>404 Not Found</h1><p>This app has no page at <code>${escapeHtml(path)}</code>.</p><p><a href="/">Back to the app</a></p></main>${scriptTag}</body></html>`;
|
|
806
|
+
}
|
|
723
807
|
function apply(ctx, rawConfig = {}) {
|
|
724
808
|
const config = Config(rawConfig);
|
|
725
809
|
if (process.env.ACRYL_DOOR === "off" || process.env.NODE_ENV === "production" && config.allowInProduction !== true) return;
|
|
@@ -741,12 +825,35 @@ function apply(ctx, rawConfig = {}) {
|
|
|
741
825
|
},
|
|
742
826
|
extensions: () => ctx.get("extensions"),
|
|
743
827
|
tools: () => ctx.get("tools"),
|
|
744
|
-
expose: config.tools?.expose ?? []
|
|
828
|
+
expose: config.tools?.expose ?? [],
|
|
829
|
+
reloadOnChange: config.reloadOnChange !== false
|
|
745
830
|
});
|
|
746
831
|
ctx.effect(() => () => {
|
|
747
832
|
channel.close();
|
|
748
833
|
}, "acryl-door: page channel");
|
|
749
834
|
const pageModule = new Acryl().get(`${DOOR_PREFIX}/page.js`, (c) => c.body(`import '${DOOR_PREFIX}/page/main.ts'\n`, 200, { "content-type": "text/javascript; charset=utf-8" })).route(`${DOOR_PREFIX}/page`, clientModules({ root: PAGE_DIR }));
|
|
835
|
+
const tag = `<script type="module" src="${DOOR_PREFIX}/page.js"><\/script>`;
|
|
836
|
+
const addScript = async (c, next) => {
|
|
837
|
+
await next();
|
|
838
|
+
if (!(c.res.headers.get("content-type") ?? "").includes("text/html")) {
|
|
839
|
+
if (c.res.status === 404 && (c.req.header("accept") ?? "").includes("text/html") && !(c.res.headers.get("content-type") ?? "").includes("json")) c.res = new Response(notFoundPage(c.req.path, tag), {
|
|
840
|
+
status: 404,
|
|
841
|
+
headers: { "content-type": "text/html; charset=utf-8" }
|
|
842
|
+
});
|
|
843
|
+
return;
|
|
844
|
+
}
|
|
845
|
+
const html = await c.res.text();
|
|
846
|
+
const headers = new Headers(c.res.headers);
|
|
847
|
+
headers.delete("content-length");
|
|
848
|
+
const carries = html.includes(`${DOOR_PREFIX}/page.js`);
|
|
849
|
+
c.res = new Response(carries ? html : html.includes("</body>") ? html.replace("</body>", `${tag}</body>`) : html + tag, {
|
|
850
|
+
status: c.res.status,
|
|
851
|
+
headers
|
|
852
|
+
});
|
|
853
|
+
};
|
|
854
|
+
const router = ctx.router;
|
|
855
|
+
if (typeof router.wrap === "function") router.wrap(addScript);
|
|
856
|
+
else ctx.router.route("/", new Acryl().use("*", addScript));
|
|
750
857
|
ctx.router.route("/", privateApi(DOOR_PREFIX, pageModule, pageChannelRoutes(channel, { prefix: DOOR_PREFIX }), operatorRoutes(DOOR_PREFIX, secret, door, reportError), mcpRoutes(DOOR_PREFIX, secret, door, reportError)));
|
|
751
858
|
ctx.inject(["tools"], (inner) => {
|
|
752
859
|
inner.effect(() => registerChatTools(inner.get("tools"), door), "acryl-door: the verbs in the tools registry");
|
|
@@ -761,4 +868,4 @@ function apply(ctx, rawConfig = {}) {
|
|
|
761
868
|
}, "acryl-door: the door service, .acryl/door.json and .acryl/bin/acryl");
|
|
762
869
|
}
|
|
763
870
|
//#endregion
|
|
764
|
-
export { Config, DOOR_PREFIX, Door, DoorError, STATE_DIR, VERBS, VERB_SPECS, apply, chatToolName, doorFilePath, inject, mcpTools, name, readDoorFile };
|
|
871
|
+
export { Config, DOOR_PREFIX, Door, DoorError, STATE_DIR, VERBS, VERB_SPECS, apply, chatToolName, doorFilePath, inject, mcpTools, name, notFoundPage, readDoorFile };
|
package/lib/cordis/inspect.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { t as Acryl } from "../app-
|
|
2
|
-
import { loopbackOnly } from "../loopback-only.js";
|
|
3
|
-
import "../src-
|
|
4
|
-
import "../middleware-
|
|
1
|
+
import { t as Acryl } from "../app-CQcGWjrk.js";
|
|
2
|
+
import { i as loopbackOnly } from "../loopback-only-BbasoF7R.js";
|
|
3
|
+
import "../src-BTBm4OPD.js";
|
|
4
|
+
import "../middleware-BfG_fp8P.js";
|
|
5
5
|
import { Service } from "@deepseek-ai/cordis";
|
|
6
6
|
//#region ../../plugins/acryl-inspect/src/report.ts
|
|
7
7
|
/**
|
package/lib/cordis/kv-db.d.ts
CHANGED
package/lib/cordis/kv-db.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import "../src-DRFVEQQb.js";
|
|
2
|
-
import { kvOnDb } from "../
|
|
2
|
+
import { t as kvOnDb } from "../open-But9E2rL.js";
|
|
3
3
|
import z from "@deepseek-ai/schemastery";
|
|
4
4
|
//#region ../../plugins/acryl-kv-db/src/index.ts
|
|
5
5
|
/** Stable Cordis plugin name, equal to the package name and the Loader row id. */
|
package/lib/cordis/kv-json.d.ts
CHANGED
package/lib/cordis/kv-json.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import "../src-DRFVEQQb.js";
|
|
2
|
-
import { openKv } from "../
|
|
2
|
+
import { t as openKv } from "../open-Dp4sxspc.js";
|
|
3
3
|
import { dirname, isAbsolute, join, resolve } from "node:path";
|
|
4
4
|
import { fileURLToPath } from "node:url";
|
|
5
5
|
import z from "@deepseek-ai/schemastery";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { c as UpgradeHubOptions, i as testWebSocket, l as UpgradeRouter, n as TestWebSocketOptions, o as UpgradeEmitter, p as WebSocketLike, r as TestWebSocketResult, s as UpgradeHub, t as TestSocket, u as RequestError } from "../test-websocket-DyeS50Tr.js";
|
|
2
2
|
import { n as UpgradeWebSocket } from "../index-C-SklY6u.js";
|
|
3
|
-
import {
|
|
3
|
+
import { n as serveStatic, t as ServeStaticOptions } from "../serve-static-B7sqnftW.js";
|
|
4
4
|
import { Context, Service } from "@deepseek-ai/cordis";
|
|
5
5
|
import z from "@deepseek-ai/schemastery";
|
|
6
6
|
|
|
@@ -1,117 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { t as serveStatic } from "../serve-static-
|
|
3
|
-
import {
|
|
4
|
-
import z from "@deepseek-ai/schemastery";
|
|
5
|
-
//#region ../../plugins/acryl-node-server/src/index.ts
|
|
6
|
-
/** Stable Cordis plugin name, equal to the package name and the Loader row id. */
|
|
7
|
-
const name = "acryl-node-server";
|
|
8
|
-
const inject = ["router"];
|
|
9
|
-
/** Every field has a default, so a caller passes only what it changes: `ctx.plugin(plugin, { ... })` takes the partial shape. */
|
|
10
|
-
const Config = z.object({
|
|
11
|
-
hostname: z.string().default("127.0.0.1").description("Address to bind. Loopback by default; binding elsewhere exposes the app to the network."),
|
|
12
|
-
port: z.number().min(0).max(65535).default(0).description("Port to listen on; 0 lets the system choose. A taken port is followed by the next free one."),
|
|
13
|
-
scan: z.number().min(0).default(20).description("How many further ports to try when the configured one is taken."),
|
|
14
|
-
websocket: z.object({
|
|
15
|
-
maxPayload: z.number().min(1).default(1024 * 1024).description("The largest WebSocket frame accepted, in bytes; a bigger one closes the socket with 1009."),
|
|
16
|
-
heartbeat: z.number().min(0).default(3e4).description("Milliseconds between pings; a peer that did not answer the last one is terminated. 0 turns it off."),
|
|
17
|
-
grace: z.number().min(0).default(2e3).description("Milliseconds a closing socket gets before it is terminated when its plugin unloads.")
|
|
18
|
-
}).default({})
|
|
19
|
-
});
|
|
20
|
-
var NodeServer = class extends Service {
|
|
21
|
-
hostname;
|
|
22
|
-
config;
|
|
23
|
-
server;
|
|
24
|
-
hub;
|
|
25
|
-
bound = 0;
|
|
26
|
-
constructor(ctx, config) {
|
|
27
|
-
super(ctx, "nodeServer");
|
|
28
|
-
this.config = config;
|
|
29
|
-
this.hostname = config.hostname;
|
|
30
|
-
const router = ctx.router;
|
|
31
|
-
this.server = createAdaptorServer({
|
|
32
|
-
fetch: (request, { incoming }) => router.fetch(new Request(request), {
|
|
33
|
-
remoteAddress: incoming.socket.remoteAddress,
|
|
34
|
-
localPort: incoming.socket.localPort
|
|
35
|
-
}),
|
|
36
|
-
hostname: config.hostname,
|
|
37
|
-
overrideGlobalObjects: false
|
|
38
|
-
});
|
|
39
|
-
ctx.effect(() => async () => {
|
|
40
|
-
await this.hub?.close();
|
|
41
|
-
this.server.closeAllConnections();
|
|
42
|
-
if (this.server.listening) await new Promise((resolve) => {
|
|
43
|
-
this.server.close(() => {
|
|
44
|
-
resolve();
|
|
45
|
-
});
|
|
46
|
-
});
|
|
47
|
-
}, "acryl-node-server: close listener and open connections");
|
|
48
|
-
}
|
|
49
|
-
/**
|
|
50
|
-
* `upgradeWebSocket` for the plugin that asks (call it once, in `apply`): `app.get('/ws', upgrade((c) => ({ onMessage(event, ws) { ... } })))`. Checks go in ordinary middleware on the
|
|
51
|
-
* route, and a handler that returns a `Response` refuses the upgrade with that status before any handshake. Every socket it accepts belongs to the calling plugin: when the plugin
|
|
52
|
-
* unloads they are closed with 1001 within `websocket.grace` and the handler sees `close` once. Pass `{ textOnly: true }` to drop binary frames. Needs the `ws` package.
|
|
53
|
-
*/
|
|
54
|
-
upgrades() {
|
|
55
|
-
if (!this.hub) {
|
|
56
|
-
this.hub = new UpgradeHub(this.config.websocket);
|
|
57
|
-
this.hub.attach(this.server, this.ctx.router);
|
|
58
|
-
}
|
|
59
|
-
return this.hub.upgradeWebSocketFor(this.ctx);
|
|
60
|
-
}
|
|
61
|
-
/** How many WebSocket connections are open now. */
|
|
62
|
-
get sockets() {
|
|
63
|
-
return this.hub?.size ?? 0;
|
|
64
|
-
}
|
|
65
|
-
/** The port in use, 0 before the server listens. */
|
|
66
|
-
get port() {
|
|
67
|
-
return this.bound;
|
|
68
|
-
}
|
|
69
|
-
/** The address clients use. */
|
|
70
|
-
get url() {
|
|
71
|
-
return `http://${this.hostname.includes(":") ? `[${this.hostname}]` : this.hostname}:${String(this.bound)}`;
|
|
72
|
-
}
|
|
73
|
-
/** Bind, scanning past taken ports. */
|
|
74
|
-
async listen() {
|
|
75
|
-
const { port, scan, hostname } = this.config;
|
|
76
|
-
const last = port === 0 ? 0 : Math.min(65535, port + scan);
|
|
77
|
-
for (let candidate = port; candidate <= last; candidate += 1) try {
|
|
78
|
-
await new Promise((resolve, reject) => {
|
|
79
|
-
const onError = (error) => {
|
|
80
|
-
reject(error);
|
|
81
|
-
};
|
|
82
|
-
this.server.once("error", onError);
|
|
83
|
-
this.server.listen(candidate, hostname, () => {
|
|
84
|
-
this.server.off("error", onError);
|
|
85
|
-
resolve();
|
|
86
|
-
});
|
|
87
|
-
});
|
|
88
|
-
this.bound = this.server.address().port;
|
|
89
|
-
return;
|
|
90
|
-
} catch (error) {
|
|
91
|
-
if (!isPortUnavailable(error)) throw error;
|
|
92
|
-
}
|
|
93
|
-
throw new Error(`acryl-node-server: no free port from ${String(port)} to ${String(last)} on ${hostname}`);
|
|
94
|
-
}
|
|
95
|
-
};
|
|
96
|
-
/**
|
|
97
|
-
* Whether a failed bind means "this port, try the next one". A port another socket holds answers `EADDRINUSE` everywhere. On Windows a port
|
|
98
|
-
* inside a range the system reserves (Hyper-V, WSL and Docker exclude ranges, `netsh interface ipv4 show excludedportrange`) answers
|
|
99
|
-
* `EACCES`, which is a property of that port too; elsewhere `EACCES` means the process may not bind low ports at all, so moving on would
|
|
100
|
-
* only hide the reason.
|
|
101
|
-
*/
|
|
102
|
-
function isPortUnavailable(error, platform = process.platform) {
|
|
103
|
-
const code = error?.code;
|
|
104
|
-
return code === "EADDRINUSE" || platform === "win32" && code === "EACCES";
|
|
105
|
-
}
|
|
106
|
-
/** Loads once the server listens, so a plugin that injects `nodeServer` can rely on `url`. A failure to bind fails the plugin. */
|
|
107
|
-
async function apply(ctx, config = {}) {
|
|
108
|
-
await new NodeServer(ctx, {
|
|
109
|
-
hostname: "127.0.0.1",
|
|
110
|
-
port: 0,
|
|
111
|
-
scan: 20,
|
|
112
|
-
websocket: {},
|
|
113
|
-
...config
|
|
114
|
-
}).listen();
|
|
115
|
-
}
|
|
116
|
-
//#endregion
|
|
1
|
+
import { l as RequestError, n as UpgradeEmitter, r as UpgradeHub, t as testWebSocket } from "../test-websocket-BLeEvybj.js";
|
|
2
|
+
import { t as serveStatic } from "../serve-static-C1Nkj_xB.js";
|
|
3
|
+
import { a as isPortUnavailable, i as inject, n as NodeServer, o as name, r as apply, t as Config } from "../src-LX0E4ec4.js";
|
|
117
4
|
export { Config, NodeServer, RequestError, UpgradeEmitter, UpgradeHub, apply, inject, isPortUnavailable, name, serveStatic, testWebSocket };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { n as UpgradeWebSocket } from "../index-C-SklY6u.js";
|
|
2
|
-
import { i as RouterHttpService } from "../index-
|
|
2
|
+
import { i as RouterHttpService } from "../index-DMOtA-NJ.js";
|
|
3
3
|
import { IncomingMessage, ServerResponse } from "node:http";
|
|
4
4
|
import { Duplex } from "node:stream";
|
|
5
5
|
import { Context, Service } from "@deepseek-ai/cordis";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { n as UpgradeEmitter, r as UpgradeHub } from "../test-websocket-
|
|
2
|
-
import "
|
|
1
|
+
import { n as UpgradeEmitter, r as UpgradeHub } from "../test-websocket-BLeEvybj.js";
|
|
2
|
+
import "../src-LX0E4ec4.js";
|
|
3
3
|
import { Readable } from "node:stream";
|
|
4
4
|
import { Service } from "@deepseek-ai/cordis";
|
|
5
5
|
import { pipeline } from "node:stream/promises";
|
package/lib/cordis/router.d.ts
CHANGED
|
@@ -2,6 +2,6 @@ import { B as NotFoundHandler, L as MiddlewareHandler, O as Handler, Q as Valida
|
|
|
2
2
|
import { c as StatusCode, n as ContentfulStatusCode } from "../http-status-DaAwGAFL.js";
|
|
3
3
|
import { a as getConnInfo, i as connectionOf, n as RouterBindings, r as RouterEnv, t as ConnectionInfo } from "../connection-ZLEso7XL.js";
|
|
4
4
|
import { t as Acryl } from "../app-D8riatvv.js";
|
|
5
|
-
import { a as TrailingSlash, i as RouterHttpService, n as MountableApp, o as apply, r as Router, s as name, t as Config } from "../index-
|
|
5
|
+
import { a as TrailingSlash, i as RouterHttpService, n as MountableApp, o as apply, r as Router, s as name, t as Config } from "../index-DMOtA-NJ.js";
|
|
6
6
|
import { t as HTTPException } from "../http-exception-kpGJkmpi.js";
|
|
7
7
|
export { Acryl, type AcrylRequest, Config, type ConnectionInfo, type ContentfulStatusCode, Context, type ContextRenderer, type ContextVariableMap, type Env, type ErrorHandler, type ExecutionContext, HTTPException, type Handler, type Input, type MiddlewareHandler, type MountableApp, type Next, type NotFoundHandler, type NotFoundResponse, Router, type RouterBindings, type RouterEnv, type RouterHttpService, type Schema, type StatusCode, type ToSchema, type TrailingSlash, type TypedResponse, type ValidationTargets, apply, connectionOf, getConnInfo, name };
|
package/lib/cordis/router.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { HTTPException } from "../http-exception.js";
|
|
2
|
-
import { t as Context } from "../context-
|
|
3
|
-
import { t as Acryl } from "../app-
|
|
1
|
+
import { t as HTTPException } from "../http-exception-MjWkT89V.js";
|
|
2
|
+
import { t as Context } from "../context-CkOh7Ygv.js";
|
|
3
|
+
import { t as Acryl } from "../app-CQcGWjrk.js";
|
|
4
4
|
import { n as getConnInfo, t as connectionOf } from "../connection-C7xgP1hP.js";
|
|
5
|
-
import { i as name, n as Router, r as apply, t as Config } from "../src-
|
|
5
|
+
import { i as name, n as Router, r as apply, t as Config } from "../src-BTBm4OPD.js";
|
|
6
6
|
export { Acryl, Config, Context, HTTPException, Router, apply, connectionOf, getConnInfo, name };
|
package/lib/cordis/state.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { t as Acryl } from "../app-
|
|
2
|
-
import { methodNotAllowed } from "../method-not-allowed.js";
|
|
3
|
-
import { r as streamSSE } from "../streaming-
|
|
4
|
-
import { loopbackOnly } from "../loopback-only.js";
|
|
5
|
-
import "../helpers-
|
|
6
|
-
import "../src-
|
|
7
|
-
import "../middleware-
|
|
1
|
+
import { t as Acryl } from "../app-CQcGWjrk.js";
|
|
2
|
+
import { t as methodNotAllowed } from "../method-not-allowed-TO2_hnfl.js";
|
|
3
|
+
import { r as streamSSE } from "../streaming-BlDaph8U.js";
|
|
4
|
+
import { i as loopbackOnly } from "../loopback-only-BbasoF7R.js";
|
|
5
|
+
import "../helpers-BEjcdbgw.js";
|
|
6
|
+
import "../src-BTBm4OPD.js";
|
|
7
|
+
import "../middleware-BfG_fp8P.js";
|
|
8
8
|
import { Service } from "@deepseek-ai/cordis";
|
|
9
9
|
//#region ../../plugins/acryl-state/src/cell.ts
|
|
10
10
|
/** A writable cell. `report` receives anything a listener throws; one failing listener never blocks the others. */
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
//#region ../../plugins/acryl-router/src/core/middleware/cors/index.ts
|
|
2
|
+
/**
|
|
3
|
+
* CORS Middleware for Acryl.
|
|
4
|
+
*
|
|
5
|
+
*
|
|
6
|
+
* @param {CORSOptions} [options] - The options for the CORS middleware.
|
|
7
|
+
* @param {string | string[] | ((origin: string, c: Context) => Promise<string | undefined | null> | string | undefined | null)} [options.origin='*'] - The value of "Access-Control-Allow-Origin" CORS header.
|
|
8
|
+
* @param {string[] | ((origin: string, c: Context) => Promise<string[]> | string[])} [options.allowMethods=['GET', 'HEAD', 'PUT', 'POST', 'DELETE', 'PATCH', 'QUERY']] - The value of "Access-Control-Allow-Methods" CORS header.
|
|
9
|
+
* @param {string[]} [options.allowHeaders=[]] - The value of "Access-Control-Allow-Headers" CORS header.
|
|
10
|
+
* @param {number} [options.maxAge] - The value of "Access-Control-Max-Age" CORS header.
|
|
11
|
+
* @param {boolean} [options.credentials] - The value of "Access-Control-Allow-Credentials" CORS header.
|
|
12
|
+
* @param {string[]} [options.exposeHeaders=[]] - The value of "Access-Control-Expose-Headers" CORS header.
|
|
13
|
+
* @returns {MiddlewareHandler} The middleware handler function.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```ts
|
|
17
|
+
* const app = new Acryl()
|
|
18
|
+
*
|
|
19
|
+
* app.use('/api/*', cors())
|
|
20
|
+
* app.use(
|
|
21
|
+
* '/api2/*',
|
|
22
|
+
* cors({
|
|
23
|
+
* origin: 'http://example.com',
|
|
24
|
+
* allowHeaders: ['X-Custom-Header', 'Upgrade-Insecure-Requests'],
|
|
25
|
+
* allowMethods: ['POST', 'GET', 'OPTIONS'],
|
|
26
|
+
* exposeHeaders: ['Content-Length', 'X-Kuma-Revision'],
|
|
27
|
+
* maxAge: 600,
|
|
28
|
+
* credentials: true,
|
|
29
|
+
* })
|
|
30
|
+
* )
|
|
31
|
+
*
|
|
32
|
+
* app.all('/api/abc', (c) => {
|
|
33
|
+
* return c.json({ success: true })
|
|
34
|
+
* })
|
|
35
|
+
* app.all('/api2/abc', (c) => {
|
|
36
|
+
* return c.json({ success: true })
|
|
37
|
+
* })
|
|
38
|
+
* ```
|
|
39
|
+
*/
|
|
40
|
+
const cors = (options) => {
|
|
41
|
+
const opts = {
|
|
42
|
+
origin: "*",
|
|
43
|
+
allowMethods: [
|
|
44
|
+
"GET",
|
|
45
|
+
"HEAD",
|
|
46
|
+
"PUT",
|
|
47
|
+
"POST",
|
|
48
|
+
"DELETE",
|
|
49
|
+
"PATCH",
|
|
50
|
+
"QUERY"
|
|
51
|
+
],
|
|
52
|
+
allowHeaders: [],
|
|
53
|
+
exposeHeaders: [],
|
|
54
|
+
...options
|
|
55
|
+
};
|
|
56
|
+
const exposeHeadersStr = opts.exposeHeaders?.length ? opts.exposeHeaders.join(",") : void 0;
|
|
57
|
+
const allowHeadersStr = opts.allowHeaders?.length ? opts.allowHeaders.join(",") : void 0;
|
|
58
|
+
const findAllowOrigin = ((optsOrigin) => {
|
|
59
|
+
if (typeof optsOrigin === "string") if (optsOrigin === "*") return () => optsOrigin;
|
|
60
|
+
else return (origin) => optsOrigin === origin ? origin : null;
|
|
61
|
+
else if (typeof optsOrigin === "function") return optsOrigin;
|
|
62
|
+
else return (origin) => optsOrigin.includes(origin) ? origin : null;
|
|
63
|
+
})(opts.origin);
|
|
64
|
+
const findAllowMethods = ((optsAllowMethods) => {
|
|
65
|
+
if (typeof optsAllowMethods === "function") return async (origin, c) => (await optsAllowMethods(origin, c)).join(",");
|
|
66
|
+
else if (Array.isArray(optsAllowMethods)) {
|
|
67
|
+
const methodsStr = optsAllowMethods.join(",");
|
|
68
|
+
return () => methodsStr;
|
|
69
|
+
} else return () => "";
|
|
70
|
+
})(opts.allowMethods);
|
|
71
|
+
return async function cors(c, next) {
|
|
72
|
+
function set(key, value) {
|
|
73
|
+
c.res.headers.set(key, value);
|
|
74
|
+
}
|
|
75
|
+
const allowOrigin = await findAllowOrigin(c.req.header("origin") || "", c);
|
|
76
|
+
if (allowOrigin) set("Access-Control-Allow-Origin", allowOrigin);
|
|
77
|
+
if (opts.credentials) set("Access-Control-Allow-Credentials", "true");
|
|
78
|
+
if (exposeHeadersStr) set("Access-Control-Expose-Headers", exposeHeadersStr);
|
|
79
|
+
if (c.req.method === "OPTIONS") {
|
|
80
|
+
if (opts.origin !== "*") c.res.headers.append("Vary", "Origin");
|
|
81
|
+
if (opts.maxAge != null) set("Access-Control-Max-Age", opts.maxAge.toString());
|
|
82
|
+
const allowMethods = await findAllowMethods(c.req.header("origin") || "", c);
|
|
83
|
+
if (allowMethods) set("Access-Control-Allow-Methods", allowMethods);
|
|
84
|
+
let headersStr = allowHeadersStr;
|
|
85
|
+
if (!headersStr) {
|
|
86
|
+
const requestHeaders = c.req.header("Access-Control-Request-Headers");
|
|
87
|
+
if (requestHeaders) headersStr = requestHeaders.split(",").map((h) => h.trim()).join(",");
|
|
88
|
+
}
|
|
89
|
+
if (headersStr) {
|
|
90
|
+
set("Access-Control-Allow-Headers", headersStr);
|
|
91
|
+
c.res.headers.append("Vary", "Access-Control-Request-Headers");
|
|
92
|
+
}
|
|
93
|
+
c.res.headers.delete("Content-Length");
|
|
94
|
+
c.res.headers.delete("Content-Type");
|
|
95
|
+
return new Response(null, {
|
|
96
|
+
headers: c.res.headers,
|
|
97
|
+
status: 204,
|
|
98
|
+
statusText: "No Content"
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
await next();
|
|
102
|
+
if (opts.origin !== "*") c.header("Vary", "Origin", { append: true });
|
|
103
|
+
};
|
|
104
|
+
};
|
|
105
|
+
//#endregion
|
|
106
|
+
export { cors as t };
|