@clawscarf/cli 0.1.0-alpha.1
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/LICENSE +21 -0
- package/README.md +3 -0
- package/THIRD_PARTY_NOTICES.md +102 -0
- package/deploy/execution/browser/LICENSE.playwright +202 -0
- package/deploy/execution/browser/seccomp.json +640 -0
- package/deploy/execution/browser-node/configuration.js +85 -0
- package/deploy/execution/browser-node/operator.js +167 -0
- package/deploy/execution/network/node-ingress.cfg +35 -0
- package/deploy/models/catalog.json +275 -0
- package/deploy/openshell/policy.yaml +24 -0
- package/generated/http/LICENSE.md +21 -0
- package/generated/http/client/client.gen.d.ts +2 -0
- package/generated/http/client/client.gen.js +216 -0
- package/generated/http/client/index.d.ts +10 -0
- package/generated/http/client/index.js +6 -0
- package/generated/http/client/types.gen.d.ts +120 -0
- package/generated/http/client/types.gen.js +2 -0
- package/generated/http/client/utils.gen.d.ts +37 -0
- package/generated/http/client/utils.gen.js +228 -0
- package/generated/http/core/auth.gen.d.ts +25 -0
- package/generated/http/core/auth.gen.js +14 -0
- package/generated/http/core/bodySerializer.gen.d.ts +25 -0
- package/generated/http/core/bodySerializer.gen.js +57 -0
- package/generated/http/core/params.gen.d.ts +43 -0
- package/generated/http/core/params.gen.js +109 -0
- package/generated/http/core/pathSerializer.gen.d.ts +33 -0
- package/generated/http/core/pathSerializer.gen.js +106 -0
- package/generated/http/core/queryKeySerializer.gen.d.ts +18 -0
- package/generated/http/core/queryKeySerializer.gen.js +92 -0
- package/generated/http/core/serverSentEvents.gen.d.ts +71 -0
- package/generated/http/core/serverSentEvents.gen.js +132 -0
- package/generated/http/core/types.gen.d.ts +83 -0
- package/generated/http/core/types.gen.js +2 -0
- package/generated/http/core/utils.gen.d.ts +19 -0
- package/generated/http/core/utils.gen.js +87 -0
- package/package.json +37 -0
- package/packs/README.md +130 -0
- package/packs/research-team/pack.json +20 -0
- package/packs/research-team/researcher/CLAW.md +19 -0
- package/packs/research-team/researcher/package.json +8 -0
- package/packs/research-team/researcher/profiles/openclaw.yml +6 -0
- package/packs/research-team/reviewer/CLAW.md +19 -0
- package/packs/research-team/reviewer/package.json +8 -0
- package/packs/research-team/reviewer/profiles/openclaw.yml +6 -0
- package/pnpm-lock.yaml +7158 -0
- package/recipes/README.md +37 -0
- package/recipes/team-server/recipe.json +28 -0
- package/release/README.md +137 -0
- package/release/components.json +29 -0
- package/release/operator.md +63 -0
- package/runtime/configuration.js +135 -0
- package/runtime/connections-configuration.js +70 -0
- package/runtime/model-contract.js +92 -0
- package/runtime/releases/0.1.0-alpha.1.json +37 -0
- package/scripts/clawscarf.js +92 -0
- package/scripts/cloud/login.js +134 -0
- package/scripts/cloud/registration.js +232 -0
- package/scripts/cloud/url.js +9 -0
- package/scripts/connections.js +193 -0
- package/scripts/controller.js +143 -0
- package/scripts/deployment/browser-node-compose.js +81 -0
- package/scripts/deployment/browser-node-helper.js +9 -0
- package/scripts/deployment/browser-node-pairing.js +165 -0
- package/scripts/deployment/browser-node.js +154 -0
- package/scripts/deployment/browser.js +143 -0
- package/scripts/deployment/certificates.js +76 -0
- package/scripts/deployment/compose.js +191 -0
- package/scripts/deployment/configuration.js +275 -0
- package/scripts/deployment/connection-policy.js +80 -0
- package/scripts/deployment/connection-settings.js +60 -0
- package/scripts/deployment/connections-runtime.js +31 -0
- package/scripts/deployment/connections.js +213 -0
- package/scripts/deployment/controller-compose.js +59 -0
- package/scripts/deployment/database.js +199 -0
- package/scripts/deployment/entrypoint.js +7 -0
- package/scripts/deployment/images.js +17 -0
- package/scripts/deployment/initial-services.js +53 -0
- package/scripts/deployment/launch.js +177 -0
- package/scripts/deployment/logs.js +15 -0
- package/scripts/deployment/model-gateway-compose.js +74 -0
- package/scripts/deployment/model-gateway.js +125 -0
- package/scripts/deployment/models.js +82 -0
- package/scripts/deployment/networks.js +354 -0
- package/scripts/deployment/policy.js +56 -0
- package/scripts/deployment/preflight.js +124 -0
- package/scripts/deployment/prepare.js +205 -0
- package/scripts/deployment/process.js +70 -0
- package/scripts/deployment/relay.js +58 -0
- package/scripts/deployment/runtime-binding.js +100 -0
- package/scripts/deployment/runtime.js +232 -0
- package/scripts/deployment/state.js +154 -0
- package/scripts/deployment/team.js +76 -0
- package/scripts/deployment/upgrade-rpc.py +148 -0
- package/scripts/deployment/upgrade-state.js +47 -0
- package/scripts/deployment/upgrade.js +298 -0
- package/scripts/deployment/volumes.js +24 -0
- package/scripts/errors.js +9 -0
- package/scripts/installation/administrator.js +23 -0
- package/scripts/installation/command.js +176 -0
- package/scripts/installation/configuration.js +104 -0
- package/scripts/installation/configure.js +122 -0
- package/scripts/installation/delete.js +111 -0
- package/scripts/installation/doctor.js +8 -0
- package/scripts/installation/errors.js +8 -0
- package/scripts/installation/files.js +51 -0
- package/scripts/installation/installer/cloud.js +22 -0
- package/scripts/installation/installer/collect.js +245 -0
- package/scripts/installation/installer/inputs.js +59 -0
- package/scripts/installation/installer/menu.js +49 -0
- package/scripts/installation/installer/prompts.js +139 -0
- package/scripts/installation/installer/run.js +251 -0
- package/scripts/installation/installer/secrets.js +16 -0
- package/scripts/installation/installer/sections/access.js +69 -0
- package/scripts/installation/installer/sections/certificates.js +18 -0
- package/scripts/installation/installer/sections/connections.js +4 -0
- package/scripts/installation/installer/sections/external-models.js +35 -0
- package/scripts/installation/installer/sections/models.js +119 -0
- package/scripts/installation/installer/sections/packs.js +82 -0
- package/scripts/installation/installer/sections/resources.js +10 -0
- package/scripts/installation/installer/settings.js +192 -0
- package/scripts/installation/installer/summary.js +44 -0
- package/scripts/installation/lifecycle.js +127 -0
- package/scripts/installation/location.js +3 -0
- package/scripts/installation/models.js +42 -0
- package/scripts/installation/options.js +360 -0
- package/scripts/installation/packs.js +150 -0
- package/scripts/installation/plan.js +121 -0
- package/scripts/installation/prerequisites.js +170 -0
- package/scripts/installation/recipes/catalog.js +55 -0
- package/scripts/installation/recipes/definition.js +32 -0
- package/scripts/installation/reconfigure.js +255 -0
- package/scripts/installation/requirements.js +23 -0
- package/scripts/installation/resolve.js +217 -0
- package/scripts/installation/runtime.js +87 -0
- package/scripts/installation/save.js +95 -0
- package/scripts/installation/setup.js +91 -0
- package/scripts/models/catalog.js +9 -0
- package/scripts/models/configuration.js +184 -0
- package/scripts/models/credentials.js +132 -0
- package/scripts/models/runtime.js +87 -0
- package/scripts/output.js +34 -0
- package/scripts/packs/connections.js +95 -0
- package/scripts/packs/lifecycle.js +125 -0
- package/scripts/packs/model.js +66 -0
- package/scripts/packs/native.js +69 -0
- package/scripts/packs/openshell.js +148 -0
- package/scripts/packs/policy.js +189 -0
- package/scripts/packs/requirements.in +1 -0
- package/scripts/packs/requirements.js +11 -0
- package/scripts/packs/requirements.txt +116 -0
- package/scripts/packs/source.js +90 -0
- package/scripts/packs/transport.py +68 -0
- package/scripts/people.js +52 -0
- package/scripts/release/create.js +62 -0
- package/scripts/release/definition.js +51 -0
- package/scripts/session.js +27 -0
- package/services/access/generated/client.gen.d.ts +12 -0
- package/services/access/generated/client.gen.js +3 -0
- package/services/access/generated/fastify.gen.d.ts +49 -0
- package/services/access/generated/fastify.gen.js +2 -0
- package/services/access/generated/index.d.ts +2 -0
- package/services/access/generated/index.js +2 -0
- package/services/access/generated/sdk.gen.d.ts +28 -0
- package/services/access/generated/sdk.gen.js +107 -0
- package/services/access/generated/types.gen.d.ts +349 -0
- package/services/access/generated/types.gen.js +2 -0
- package/services/access/migrations/001_access.sql +39 -0
- package/services/access/migrations/002_administrator_setup.sql +16 -0
- package/services/access/migrations/003_local_login_completion.sql +5 -0
- package/services/access/migrations/004_invitations.sql +21 -0
- package/services/access/repo/postgres.js +341 -0
- package/services/access/repo/session-logout.js +28 -0
- package/services/access/types/credential.js +2 -0
- package/services/access/types/errors.js +7 -0
- package/services/access/types/ingress.js +1 -0
- package/services/access/types/model.js +1 -0
- package/services/access/types/native-errors.js +7 -0
- package/services/access/types/native.js +1 -0
- package/services/cloud/generated/client.gen.d.ts +12 -0
- package/services/cloud/generated/client.gen.js +3 -0
- package/services/cloud/generated/index.d.ts +2 -0
- package/services/cloud/generated/index.js +2 -0
- package/services/cloud/generated/sdk.gen.d.ts +145 -0
- package/services/cloud/generated/sdk.gen.js +488 -0
- package/services/cloud/generated/types.gen.d.ts +2034 -0
- package/services/cloud/generated/types.gen.js +2 -0
- package/services/connections/cloud/generated/client.gen.d.ts +12 -0
- package/services/connections/cloud/generated/client.gen.js +3 -0
- package/services/connections/cloud/generated/fastify.gen.d.ts +68 -0
- package/services/connections/cloud/generated/fastify.gen.js +2 -0
- package/services/connections/cloud/generated/index.d.ts +2 -0
- package/services/connections/cloud/generated/index.js +2 -0
- package/services/connections/cloud/generated/sdk.gen.d.ts +95 -0
- package/services/connections/cloud/generated/sdk.gen.js +210 -0
- package/services/connections/cloud/generated/types.gen.d.ts +1044 -0
- package/services/connections/cloud/generated/types.gen.js +2 -0
- package/services/connections/migrations/001_connections.sql +220 -0
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { isDeepStrictEqual } from "node:util";
|
|
2
|
+
/** The node's policy is operator-owned; only its fixed CDP destination varies. */
|
|
3
|
+
export function browserNodeConfiguration(cdpUrl) {
|
|
4
|
+
const url = new URL(cdpUrl);
|
|
5
|
+
if (!["http:", "https:"].includes(url.protocol) ||
|
|
6
|
+
!url.hostname ||
|
|
7
|
+
url.username !== "openclaw" ||
|
|
8
|
+
decodeURIComponent(url.password).length < 32 ||
|
|
9
|
+
url.hash ||
|
|
10
|
+
url.search ||
|
|
11
|
+
(url.pathname !== "/" && url.pathname !== "")) {
|
|
12
|
+
throw new Error("Browser node requires an authenticated HTTP CDP origin");
|
|
13
|
+
}
|
|
14
|
+
return {
|
|
15
|
+
tools: { exec: { mode: "deny" } },
|
|
16
|
+
plugins: { allow: ["browser"], entries: { browser: { enabled: true } } },
|
|
17
|
+
nodeHost: {
|
|
18
|
+
workerRuns: { enabled: false },
|
|
19
|
+
agentRuns: { claude: { enabled: false } },
|
|
20
|
+
skills: { enabled: false },
|
|
21
|
+
browserProxy: { enabled: true, allowProfiles: ["team"] },
|
|
22
|
+
},
|
|
23
|
+
desktop: { host: { enabled: false } },
|
|
24
|
+
browser: {
|
|
25
|
+
enabled: true,
|
|
26
|
+
defaultProfile: "team",
|
|
27
|
+
profiles: { team: { cdpUrl, attachOnly: true } },
|
|
28
|
+
ssrfPolicy: { allowedHostnames: [url.hostname] },
|
|
29
|
+
},
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
export function validateBrowserNodeConfiguration(value) {
|
|
33
|
+
function object(input) {
|
|
34
|
+
if (!input || typeof input !== "object" || Array.isArray(input)) {
|
|
35
|
+
throw new Error("Invalid browser node configuration");
|
|
36
|
+
}
|
|
37
|
+
return Object.fromEntries(Object.entries(input));
|
|
38
|
+
}
|
|
39
|
+
const root = object(value);
|
|
40
|
+
const profiles = object(object(root.browser).profiles);
|
|
41
|
+
const cdpUrl = object(profiles.team).cdpUrl;
|
|
42
|
+
if (typeof cdpUrl !== "string" ||
|
|
43
|
+
!isDeepStrictEqual(value, browserNodeConfiguration(cdpUrl))) {
|
|
44
|
+
throw new Error("Browser node configuration must retain its fixed policy");
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
export function nodeArguments(input) {
|
|
48
|
+
const url = new URL(input.gatewayUrl);
|
|
49
|
+
if (!["ws:", "wss:"].includes(url.protocol) ||
|
|
50
|
+
url.username ||
|
|
51
|
+
url.password ||
|
|
52
|
+
url.search ||
|
|
53
|
+
url.hash ||
|
|
54
|
+
!input.displayName.trim() ||
|
|
55
|
+
(url.protocol === "ws:" && !input.allowPrivatePlaintext)) {
|
|
56
|
+
throw new Error("Browser node requires an explicit secure Gateway endpoint");
|
|
57
|
+
}
|
|
58
|
+
if (input.tlsFingerprint &&
|
|
59
|
+
!/^(?:[a-f\d]{2}:?){32}$/i.test(input.tlsFingerprint)) {
|
|
60
|
+
throw new Error("Invalid Gateway certificate fingerprint");
|
|
61
|
+
}
|
|
62
|
+
if (input.tlsFingerprint && url.protocol !== "wss:") {
|
|
63
|
+
throw new Error("Gateway certificate pin requires TLS");
|
|
64
|
+
}
|
|
65
|
+
return [
|
|
66
|
+
process.execPath,
|
|
67
|
+
"/app/openclaw.mjs",
|
|
68
|
+
"node",
|
|
69
|
+
"run",
|
|
70
|
+
"--host",
|
|
71
|
+
url.hostname,
|
|
72
|
+
"--port",
|
|
73
|
+
url.port || (url.protocol === "wss:" ? "443" : "80"),
|
|
74
|
+
"--context-path",
|
|
75
|
+
url.pathname,
|
|
76
|
+
url.protocol === "wss:" ? "--tls" : "--no-tls",
|
|
77
|
+
"--display-name",
|
|
78
|
+
input.displayName,
|
|
79
|
+
"--no-share-installed-apps",
|
|
80
|
+
...(input.tlsFingerprint
|
|
81
|
+
? ["--tls-fingerprint", input.tlsFingerprint]
|
|
82
|
+
: []),
|
|
83
|
+
...(input.pairingCode ? ["--pair", input.pairingCode] : []),
|
|
84
|
+
];
|
|
85
|
+
}
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import { isDeepStrictEqual } from "node:util";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
const owner = z.uuid();
|
|
5
|
+
const inputSchema = z.discriminatedUnion("command", [
|
|
6
|
+
z.strictObject({
|
|
7
|
+
command: z.literal("initialize"),
|
|
8
|
+
ownerId: owner,
|
|
9
|
+
configuration: z.record(z.string(), z.unknown()),
|
|
10
|
+
}),
|
|
11
|
+
z.strictObject({ command: z.literal("issue"), gatewayUrl: z.url() }),
|
|
12
|
+
z.strictObject({
|
|
13
|
+
command: z.literal("observe"),
|
|
14
|
+
name: z.string(),
|
|
15
|
+
nodeId: z.string().optional(),
|
|
16
|
+
}),
|
|
17
|
+
z.strictObject({
|
|
18
|
+
command: z.literal("write-code"),
|
|
19
|
+
ownerId: owner,
|
|
20
|
+
setupCode: z.string().min(1),
|
|
21
|
+
}),
|
|
22
|
+
z.strictObject({ command: z.literal("remove-code"), ownerId: owner }),
|
|
23
|
+
]);
|
|
24
|
+
const paired = z.object({
|
|
25
|
+
deviceId: z.string(),
|
|
26
|
+
displayName: z.string().optional(),
|
|
27
|
+
roles: z.array(z.string()).optional(),
|
|
28
|
+
scopes: z.array(z.string()).optional(),
|
|
29
|
+
tokens: z
|
|
30
|
+
.object({
|
|
31
|
+
node: z.object({ revokedAtMs: z.number().optional() }).optional(),
|
|
32
|
+
})
|
|
33
|
+
.optional(),
|
|
34
|
+
nodeSurface: z
|
|
35
|
+
.object({
|
|
36
|
+
displayName: z.string().optional(),
|
|
37
|
+
commands: z.array(z.string()).optional(),
|
|
38
|
+
lastConnectedAtMs: z.number().optional(),
|
|
39
|
+
lastDisconnectedAtMs: z.number().optional(),
|
|
40
|
+
})
|
|
41
|
+
.optional(),
|
|
42
|
+
});
|
|
43
|
+
function owned(path, ownerId) {
|
|
44
|
+
const marker = path + "/.clawscarf-owner";
|
|
45
|
+
const stat = fs.lstatSync(marker);
|
|
46
|
+
if (!stat.isFile() ||
|
|
47
|
+
stat.nlink !== 1 ||
|
|
48
|
+
fs.readFileSync(marker, "utf8") !== ownerId)
|
|
49
|
+
throw new Error("Volume ownership differs");
|
|
50
|
+
}
|
|
51
|
+
async function sdkCall(name, args) {
|
|
52
|
+
const specifier = "openclaw/plugin-sdk/device-bootstrap";
|
|
53
|
+
const loaded = await import(specifier);
|
|
54
|
+
const sdk = z.record(z.string(), z.unknown()).parse(loaded);
|
|
55
|
+
const method = sdk[name];
|
|
56
|
+
if (typeof method !== "function")
|
|
57
|
+
throw new Error("Native SDK unavailable");
|
|
58
|
+
const result = await Reflect.apply(method, undefined, args);
|
|
59
|
+
return result;
|
|
60
|
+
}
|
|
61
|
+
/** Operator-only helper; its stdout is private transport, never diagnostic output. */
|
|
62
|
+
async function main() {
|
|
63
|
+
let text = "";
|
|
64
|
+
for await (const chunk of process.stdin) {
|
|
65
|
+
text += String(chunk);
|
|
66
|
+
if (text.length > 131072)
|
|
67
|
+
throw new Error("Input too large");
|
|
68
|
+
}
|
|
69
|
+
const input = inputSchema.parse(JSON.parse(text));
|
|
70
|
+
if (input.command === "issue") {
|
|
71
|
+
const issued = z
|
|
72
|
+
.object({ token: z.string(), expiresAtMs: z.number() })
|
|
73
|
+
.parse(await sdkCall("issueDeviceBootstrapToken", [
|
|
74
|
+
{
|
|
75
|
+
baseDir: "/home/node/.openclaw",
|
|
76
|
+
profile: { roles: ["node"], scopes: [] },
|
|
77
|
+
},
|
|
78
|
+
]));
|
|
79
|
+
return {
|
|
80
|
+
setupCode: encodeBrowserSetupCode(input.gatewayUrl, issued),
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
if (input.command === "observe") {
|
|
84
|
+
const result = z
|
|
85
|
+
.object({ paired: z.array(paired) })
|
|
86
|
+
.parse(await sdkCall("listDevicePairing", ["/home/node/.openclaw"]));
|
|
87
|
+
return result.paired
|
|
88
|
+
.filter((value) => input.nodeId
|
|
89
|
+
? value.deviceId === input.nodeId
|
|
90
|
+
: (value.nodeSurface?.displayName ?? value.displayName) ===
|
|
91
|
+
input.name)
|
|
92
|
+
.map((value) => ({
|
|
93
|
+
nodeId: value.deviceId,
|
|
94
|
+
admitted: value.roles?.length === 1 &&
|
|
95
|
+
value.roles[0] === "node" &&
|
|
96
|
+
!value.scopes?.length &&
|
|
97
|
+
value.tokens?.node !== undefined &&
|
|
98
|
+
value.tokens.node.revokedAtMs === undefined &&
|
|
99
|
+
value.nodeSurface?.commands?.includes("browser.proxy") === true,
|
|
100
|
+
connectedAt: value.nodeSurface?.lastConnectedAtMs ?? null,
|
|
101
|
+
disconnectedAt: value.nodeSurface?.lastDisconnectedAtMs ?? null,
|
|
102
|
+
}));
|
|
103
|
+
}
|
|
104
|
+
if (input.command === "initialize") {
|
|
105
|
+
for (const path of ["/state", "/configuration"]) {
|
|
106
|
+
const marker = path + "/.clawscarf-owner";
|
|
107
|
+
if (fs.existsSync(marker))
|
|
108
|
+
owned(path, input.ownerId);
|
|
109
|
+
else {
|
|
110
|
+
if (fs.readdirSync(path).length)
|
|
111
|
+
throw new Error("Unowned data");
|
|
112
|
+
fs.writeFileSync(marker, input.ownerId, { flag: "wx", mode: 0o444 });
|
|
113
|
+
fs.chownSync(path, 1000, 1000);
|
|
114
|
+
fs.chmodSync(path, 0o700);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
const path = "/configuration/openclaw.json";
|
|
118
|
+
if (fs.existsSync(path)) {
|
|
119
|
+
const stat = fs.lstatSync(path);
|
|
120
|
+
if (!stat.isFile() ||
|
|
121
|
+
stat.nlink !== 1 ||
|
|
122
|
+
!isDeepStrictEqual(JSON.parse(fs.readFileSync(path, "utf8")), input.configuration))
|
|
123
|
+
throw new Error("Configuration differs");
|
|
124
|
+
}
|
|
125
|
+
else {
|
|
126
|
+
fs.writeFileSync(path, JSON.stringify(input.configuration), {
|
|
127
|
+
flag: "wx",
|
|
128
|
+
mode: 0o600,
|
|
129
|
+
});
|
|
130
|
+
fs.chownSync(path, 1000, 1000);
|
|
131
|
+
}
|
|
132
|
+
return { ok: true };
|
|
133
|
+
}
|
|
134
|
+
owned("/configuration", input.ownerId);
|
|
135
|
+
const path = "/configuration/pairing-code";
|
|
136
|
+
if (input.command === "write-code") {
|
|
137
|
+
fs.writeFileSync(path, input.setupCode, { flag: "wx", mode: 0o600 });
|
|
138
|
+
fs.chownSync(path, 1000, 1000);
|
|
139
|
+
}
|
|
140
|
+
else
|
|
141
|
+
fs.rmSync(path, { force: true });
|
|
142
|
+
return { ok: true };
|
|
143
|
+
}
|
|
144
|
+
export async function runBrowserOperator() {
|
|
145
|
+
try {
|
|
146
|
+
process.stdout.write(JSON.stringify(await main()));
|
|
147
|
+
}
|
|
148
|
+
catch {
|
|
149
|
+
process.stderr.write("Browser operator helper failed; private inputs omitted.\n");
|
|
150
|
+
process.exitCode = 1;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
export function encodeBrowserSetupCode(gatewayUrl, issued) {
|
|
154
|
+
const url = new URL(gatewayUrl);
|
|
155
|
+
if (url.protocol !== "wss:" ||
|
|
156
|
+
url.username ||
|
|
157
|
+
url.password ||
|
|
158
|
+
url.search ||
|
|
159
|
+
url.hash ||
|
|
160
|
+
url.pathname !== "/")
|
|
161
|
+
throw new Error("A private TLS Gateway origin is required");
|
|
162
|
+
return Buffer.from(JSON.stringify({
|
|
163
|
+
url: url.origin,
|
|
164
|
+
bootstrapToken: issued.token,
|
|
165
|
+
expiresAtMs: issued.expiresAtMs,
|
|
166
|
+
})).toString("base64url");
|
|
167
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
global
|
|
2
|
+
maxconn 64
|
|
3
|
+
nbthread 1
|
|
4
|
+
|
|
5
|
+
defaults
|
|
6
|
+
mode http
|
|
7
|
+
timeout connect 5s
|
|
8
|
+
timeout http-request 10s
|
|
9
|
+
timeout http-keep-alive 5s
|
|
10
|
+
timeout client 30s
|
|
11
|
+
timeout server 30s
|
|
12
|
+
timeout tunnel 0
|
|
13
|
+
|
|
14
|
+
resolvers docker
|
|
15
|
+
nameserver dns 127.0.0.11:53
|
|
16
|
+
resolve_retries 3
|
|
17
|
+
timeout resolve 1s
|
|
18
|
+
timeout retry 1s
|
|
19
|
+
hold valid 10s
|
|
20
|
+
|
|
21
|
+
frontend native_node
|
|
22
|
+
bind "${CLAWSCARF_NODE_INGRESS_ADDRESS}:18803" ssl crt /run/clawscarf/node-ingress.pem
|
|
23
|
+
http-request deny deny_status 404 unless { method GET } { path / } { hdr(Upgrade) -i websocket }
|
|
24
|
+
http-request deny deny_status 403 if { req.hdr(Origin) -m found }
|
|
25
|
+
http-request del-header x-openclaw- -m beg
|
|
26
|
+
http-request del-header x-forwarded- -m beg
|
|
27
|
+
http-request del-header forwarded
|
|
28
|
+
http-request del-header x-real-ip
|
|
29
|
+
http-request del-header remote-user
|
|
30
|
+
http-request del-header authorization
|
|
31
|
+
http-request del-header cookie
|
|
32
|
+
default_backend native_gateway
|
|
33
|
+
|
|
34
|
+
backend native_gateway
|
|
35
|
+
server gateway "host.docker.internal:${CLAWSCARF_NODE_GATEWAY_PORT}" resolvers docker init-addr libc,none
|
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
[
|
|
2
|
+
{
|
|
3
|
+
"provider": "OpenAI",
|
|
4
|
+
"model": {
|
|
5
|
+
"id": "gpt-6-astra",
|
|
6
|
+
"name": "OpenAI: GPT-6 Astra",
|
|
7
|
+
"enabled": true,
|
|
8
|
+
"contextWindow": 1050000,
|
|
9
|
+
"maxTokens": 128000,
|
|
10
|
+
"reasoning": true,
|
|
11
|
+
"tools": true,
|
|
12
|
+
"input": ["text"],
|
|
13
|
+
"route": {
|
|
14
|
+
"model": "openai/gpt-6-astra",
|
|
15
|
+
"apiKeyEnv": "OPENAI_API_KEY"
|
|
16
|
+
},
|
|
17
|
+
"api": "openai-responses"
|
|
18
|
+
},
|
|
19
|
+
"reasoningLevels": ["low", "medium", "high"]
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
"provider": "OpenAI",
|
|
23
|
+
"model": {
|
|
24
|
+
"id": "gpt-5.6-terra",
|
|
25
|
+
"name": "OpenAI: GPT-5.6 Terra",
|
|
26
|
+
"enabled": true,
|
|
27
|
+
"contextWindow": 1050000,
|
|
28
|
+
"maxTokens": 128000,
|
|
29
|
+
"reasoning": true,
|
|
30
|
+
"tools": true,
|
|
31
|
+
"input": ["text"],
|
|
32
|
+
"route": {
|
|
33
|
+
"model": "openai/gpt-5.6-terra",
|
|
34
|
+
"apiKeyEnv": "OPENAI_API_KEY"
|
|
35
|
+
},
|
|
36
|
+
"api": "openai-responses"
|
|
37
|
+
},
|
|
38
|
+
"reasoningLevels": ["low", "medium", "high"]
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
"provider": "OpenAI",
|
|
42
|
+
"model": {
|
|
43
|
+
"id": "gpt-5.6-luna",
|
|
44
|
+
"name": "OpenAI: GPT-5.6 Luna",
|
|
45
|
+
"enabled": true,
|
|
46
|
+
"contextWindow": 1050000,
|
|
47
|
+
"maxTokens": 128000,
|
|
48
|
+
"reasoning": true,
|
|
49
|
+
"tools": true,
|
|
50
|
+
"input": ["text"],
|
|
51
|
+
"route": {
|
|
52
|
+
"model": "openai/gpt-5.6-luna",
|
|
53
|
+
"apiKeyEnv": "OPENAI_API_KEY"
|
|
54
|
+
},
|
|
55
|
+
"api": "openai-responses"
|
|
56
|
+
},
|
|
57
|
+
"reasoningLevels": ["low", "medium", "high"]
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
"provider": "Anthropic",
|
|
61
|
+
"model": {
|
|
62
|
+
"id": "claude-fable-5.1",
|
|
63
|
+
"name": "Anthropic: Claude Fable 5.1",
|
|
64
|
+
"enabled": true,
|
|
65
|
+
"contextWindow": 1000000,
|
|
66
|
+
"maxTokens": 128000,
|
|
67
|
+
"reasoning": true,
|
|
68
|
+
"tools": true,
|
|
69
|
+
"input": ["text"],
|
|
70
|
+
"route": {
|
|
71
|
+
"model": "anthropic/claude-fable-5.1",
|
|
72
|
+
"apiKeyEnv": "ANTHROPIC_API_KEY"
|
|
73
|
+
}
|
|
74
|
+
},
|
|
75
|
+
"reasoningLevels": ["low", "medium", "high"]
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
"provider": "Anthropic",
|
|
79
|
+
"model": {
|
|
80
|
+
"id": "claude-opus-5",
|
|
81
|
+
"name": "Claude Opus 5",
|
|
82
|
+
"enabled": true,
|
|
83
|
+
"contextWindow": 1000000,
|
|
84
|
+
"maxTokens": 128000,
|
|
85
|
+
"reasoning": true,
|
|
86
|
+
"tools": true,
|
|
87
|
+
"input": ["text"],
|
|
88
|
+
"route": {
|
|
89
|
+
"model": "anthropic/claude-opus-5",
|
|
90
|
+
"apiKeyEnv": "ANTHROPIC_API_KEY"
|
|
91
|
+
}
|
|
92
|
+
},
|
|
93
|
+
"reasoningLevels": ["low", "medium", "high"]
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
"provider": "Anthropic",
|
|
97
|
+
"model": {
|
|
98
|
+
"id": "claude-sonnet-5",
|
|
99
|
+
"name": "Anthropic: Claude Sonnet 5",
|
|
100
|
+
"enabled": true,
|
|
101
|
+
"contextWindow": 1000000,
|
|
102
|
+
"maxTokens": 128000,
|
|
103
|
+
"reasoning": true,
|
|
104
|
+
"tools": true,
|
|
105
|
+
"input": ["text"],
|
|
106
|
+
"route": {
|
|
107
|
+
"model": "anthropic/claude-sonnet-5",
|
|
108
|
+
"apiKeyEnv": "ANTHROPIC_API_KEY"
|
|
109
|
+
}
|
|
110
|
+
},
|
|
111
|
+
"reasoningLevels": ["low", "medium", "high"]
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
"provider": "Google AI Studio",
|
|
115
|
+
"model": {
|
|
116
|
+
"id": "gemini-3.8-flash",
|
|
117
|
+
"name": "Google: Gemini 3.8 Flash",
|
|
118
|
+
"enabled": true,
|
|
119
|
+
"contextWindow": 1048576,
|
|
120
|
+
"maxTokens": 65536,
|
|
121
|
+
"reasoning": true,
|
|
122
|
+
"tools": true,
|
|
123
|
+
"input": ["text"],
|
|
124
|
+
"route": {
|
|
125
|
+
"model": "gemini/gemini-3.8-flash",
|
|
126
|
+
"apiKeyEnv": "GEMINI_API_KEY"
|
|
127
|
+
}
|
|
128
|
+
},
|
|
129
|
+
"reasoningLevels": ["low", "medium", "high"]
|
|
130
|
+
},
|
|
131
|
+
{
|
|
132
|
+
"provider": "OpenRouter",
|
|
133
|
+
"model": {
|
|
134
|
+
"id": "gpt-6-astra",
|
|
135
|
+
"name": "OpenAI: GPT-6 Astra",
|
|
136
|
+
"enabled": true,
|
|
137
|
+
"contextWindow": 1050000,
|
|
138
|
+
"maxTokens": 128000,
|
|
139
|
+
"reasoning": true,
|
|
140
|
+
"tools": true,
|
|
141
|
+
"input": ["text"],
|
|
142
|
+
"route": {
|
|
143
|
+
"model": "openrouter/openai/gpt-6-astra",
|
|
144
|
+
"apiKeyEnv": "OPENROUTER_API_KEY"
|
|
145
|
+
}
|
|
146
|
+
},
|
|
147
|
+
"reasoningLevels": ["low", "medium", "high"]
|
|
148
|
+
},
|
|
149
|
+
{
|
|
150
|
+
"provider": "OpenRouter",
|
|
151
|
+
"model": {
|
|
152
|
+
"id": "gpt-5.6-terra",
|
|
153
|
+
"name": "OpenAI: GPT-5.6 Terra",
|
|
154
|
+
"enabled": true,
|
|
155
|
+
"contextWindow": 1050000,
|
|
156
|
+
"maxTokens": 128000,
|
|
157
|
+
"reasoning": true,
|
|
158
|
+
"tools": true,
|
|
159
|
+
"input": ["text"],
|
|
160
|
+
"route": {
|
|
161
|
+
"model": "openrouter/openai/gpt-5.6-terra",
|
|
162
|
+
"apiKeyEnv": "OPENROUTER_API_KEY"
|
|
163
|
+
}
|
|
164
|
+
},
|
|
165
|
+
"reasoningLevels": ["low", "medium", "high"]
|
|
166
|
+
},
|
|
167
|
+
{
|
|
168
|
+
"provider": "OpenRouter",
|
|
169
|
+
"model": {
|
|
170
|
+
"id": "gpt-5.6-luna",
|
|
171
|
+
"name": "OpenAI: GPT-5.6 Luna",
|
|
172
|
+
"enabled": true,
|
|
173
|
+
"contextWindow": 1050000,
|
|
174
|
+
"maxTokens": 128000,
|
|
175
|
+
"reasoning": true,
|
|
176
|
+
"tools": true,
|
|
177
|
+
"input": ["text"],
|
|
178
|
+
"route": {
|
|
179
|
+
"model": "openrouter/openai/gpt-5.6-luna",
|
|
180
|
+
"apiKeyEnv": "OPENROUTER_API_KEY"
|
|
181
|
+
}
|
|
182
|
+
},
|
|
183
|
+
"reasoningLevels": ["low", "medium", "high"]
|
|
184
|
+
},
|
|
185
|
+
{
|
|
186
|
+
"provider": "OpenRouter",
|
|
187
|
+
"model": {
|
|
188
|
+
"id": "claude-fable-5.1",
|
|
189
|
+
"name": "Anthropic: Claude Fable 5.1",
|
|
190
|
+
"enabled": true,
|
|
191
|
+
"contextWindow": 1000000,
|
|
192
|
+
"maxTokens": 128000,
|
|
193
|
+
"reasoning": true,
|
|
194
|
+
"tools": true,
|
|
195
|
+
"input": ["text"],
|
|
196
|
+
"route": {
|
|
197
|
+
"model": "openrouter/anthropic/claude-fable-5.1",
|
|
198
|
+
"apiKeyEnv": "OPENROUTER_API_KEY"
|
|
199
|
+
}
|
|
200
|
+
},
|
|
201
|
+
"reasoningLevels": ["low", "medium", "high"]
|
|
202
|
+
},
|
|
203
|
+
{
|
|
204
|
+
"provider": "OpenRouter",
|
|
205
|
+
"model": {
|
|
206
|
+
"id": "claude-opus-5",
|
|
207
|
+
"name": "Claude Opus 5",
|
|
208
|
+
"enabled": true,
|
|
209
|
+
"contextWindow": 1000000,
|
|
210
|
+
"maxTokens": 128000,
|
|
211
|
+
"reasoning": true,
|
|
212
|
+
"tools": true,
|
|
213
|
+
"input": ["text"],
|
|
214
|
+
"route": {
|
|
215
|
+
"model": "openrouter/anthropic/claude-opus-5",
|
|
216
|
+
"apiKeyEnv": "OPENROUTER_API_KEY"
|
|
217
|
+
}
|
|
218
|
+
},
|
|
219
|
+
"reasoningLevels": ["low", "medium", "high"]
|
|
220
|
+
},
|
|
221
|
+
{
|
|
222
|
+
"provider": "OpenRouter",
|
|
223
|
+
"model": {
|
|
224
|
+
"id": "claude-sonnet-5",
|
|
225
|
+
"name": "Anthropic: Claude Sonnet 5",
|
|
226
|
+
"enabled": true,
|
|
227
|
+
"contextWindow": 1000000,
|
|
228
|
+
"maxTokens": 128000,
|
|
229
|
+
"reasoning": true,
|
|
230
|
+
"tools": true,
|
|
231
|
+
"input": ["text"],
|
|
232
|
+
"route": {
|
|
233
|
+
"model": "openrouter/anthropic/claude-sonnet-5",
|
|
234
|
+
"apiKeyEnv": "OPENROUTER_API_KEY"
|
|
235
|
+
}
|
|
236
|
+
},
|
|
237
|
+
"reasoningLevels": ["low", "medium", "high"]
|
|
238
|
+
},
|
|
239
|
+
{
|
|
240
|
+
"provider": "OpenRouter",
|
|
241
|
+
"model": {
|
|
242
|
+
"id": "gemini-3.8-flash",
|
|
243
|
+
"name": "Google: Gemini 3.8 Flash",
|
|
244
|
+
"enabled": true,
|
|
245
|
+
"contextWindow": 1048576,
|
|
246
|
+
"maxTokens": 65536,
|
|
247
|
+
"reasoning": true,
|
|
248
|
+
"tools": true,
|
|
249
|
+
"input": ["text"],
|
|
250
|
+
"route": {
|
|
251
|
+
"model": "openrouter/google/gemini-3.8-flash",
|
|
252
|
+
"apiKeyEnv": "OPENROUTER_API_KEY"
|
|
253
|
+
}
|
|
254
|
+
},
|
|
255
|
+
"reasoningLevels": ["low", "medium", "high"]
|
|
256
|
+
},
|
|
257
|
+
{
|
|
258
|
+
"provider": "OpenRouter",
|
|
259
|
+
"model": {
|
|
260
|
+
"id": "kimi-k3",
|
|
261
|
+
"name": "MoonshotAI: Kimi K3",
|
|
262
|
+
"enabled": true,
|
|
263
|
+
"contextWindow": 1048576,
|
|
264
|
+
"maxTokens": 943718,
|
|
265
|
+
"reasoning": true,
|
|
266
|
+
"tools": true,
|
|
267
|
+
"input": ["text"],
|
|
268
|
+
"route": {
|
|
269
|
+
"model": "openrouter/moonshotai/kimi-k3",
|
|
270
|
+
"apiKeyEnv": "OPENROUTER_API_KEY"
|
|
271
|
+
}
|
|
272
|
+
},
|
|
273
|
+
"reasoningLevels": ["low", "high"]
|
|
274
|
+
}
|
|
275
|
+
]
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
version: 1
|
|
2
|
+
filesystem_policy:
|
|
3
|
+
include_workdir: true
|
|
4
|
+
read_only:
|
|
5
|
+
- /app
|
|
6
|
+
- /usr
|
|
7
|
+
- /lib
|
|
8
|
+
- /etc
|
|
9
|
+
- /proc
|
|
10
|
+
- /sys/fs/cgroup
|
|
11
|
+
- /sys/devices/system/cpu
|
|
12
|
+
- /dev/urandom
|
|
13
|
+
- /dev/random
|
|
14
|
+
read_write:
|
|
15
|
+
- /home/node
|
|
16
|
+
- /tmp
|
|
17
|
+
- /dev/null
|
|
18
|
+
- /dev/shm
|
|
19
|
+
landlock:
|
|
20
|
+
compatibility: hard_requirement
|
|
21
|
+
process:
|
|
22
|
+
run_as_user: "1000"
|
|
23
|
+
run_as_group: "1000"
|
|
24
|
+
network_policies: {}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) Hey API
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|