@oharness/engine 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +26 -0
- package/dist/agent/agent.d.ts +11 -0
- package/dist/agent/agent.js +30 -9
- package/dist/agent/agent.js.map +1 -1
- package/dist/agent/hooks.d.ts +2 -0
- package/dist/agent/hooks.js +11 -0
- package/dist/agent/hooks.js.map +1 -1
- package/dist/agent/memory.d.ts +10 -1
- package/dist/agent/memory.js +147 -49
- package/dist/agent/memory.js.map +1 -1
- package/dist/agent/permissions.js +21 -3
- package/dist/agent/permissions.js.map +1 -1
- package/dist/artifacts/publish.d.ts +2 -2
- package/dist/artifacts/publish.js +2 -2
- package/dist/auth/index.d.ts +1 -1
- package/dist/auth/index.js +1 -1
- package/dist/auth/index.js.map +1 -1
- package/dist/auth/manager.d.ts +14 -0
- package/dist/auth/manager.js +25 -5
- package/dist/auth/manager.js.map +1 -1
- package/dist/auth/providers/account.d.ts +10 -45
- package/dist/auth/providers/account.js +123 -233
- package/dist/auth/providers/account.js.map +1 -1
- package/dist/config-files.d.ts +27 -0
- package/dist/config-files.js +116 -0
- package/dist/config-files.js.map +1 -0
- package/dist/config.d.ts +5 -25
- package/dist/config.js +16 -2
- package/dist/config.js.map +1 -1
- package/dist/core/audit.d.ts +20 -0
- package/dist/core/audit.js +2 -0
- package/dist/core/audit.js.map +1 -0
- package/dist/harness.d.ts +35 -2
- package/dist/harness.js +162 -50
- package/dist/harness.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/providers/registry.d.ts +42 -0
- package/dist/providers/registry.js +71 -9
- package/dist/providers/registry.js.map +1 -1
- package/dist/runtime-plugins/audit.d.ts +11 -0
- package/dist/runtime-plugins/audit.js +31 -0
- package/dist/runtime-plugins/audit.js.map +1 -0
- package/dist/runtime-plugins/builtin/jsonl-audit.d.ts +7 -0
- package/dist/runtime-plugins/builtin/jsonl-audit.js +24 -0
- package/dist/runtime-plugins/builtin/jsonl-audit.js.map +1 -0
- package/dist/runtime-plugins/builtin/memory.d.ts +70 -0
- package/dist/runtime-plugins/builtin/memory.js +360 -0
- package/dist/runtime-plugins/builtin/memory.js.map +1 -0
- package/dist/runtime-plugins/cloud-connector.d.ts +56 -0
- package/dist/runtime-plugins/cloud-connector.js +261 -0
- package/dist/runtime-plugins/cloud-connector.js.map +1 -0
- package/dist/runtime-plugins/composio/client.d.ts +65 -0
- package/dist/runtime-plugins/composio/client.js +190 -0
- package/dist/runtime-plugins/composio/client.js.map +1 -0
- package/dist/runtime-plugins/composio/index.d.ts +23 -0
- package/dist/runtime-plugins/composio/index.js +113 -0
- package/dist/runtime-plugins/composio/index.js.map +1 -0
- package/dist/runtime-plugins/connector.d.ts +15 -0
- package/dist/runtime-plugins/connector.js +17 -0
- package/dist/runtime-plugins/connector.js.map +1 -0
- package/dist/runtime-plugins/extensions.d.ts +21 -0
- package/dist/runtime-plugins/extensions.js +23 -0
- package/dist/runtime-plugins/extensions.js.map +1 -0
- package/dist/runtime-plugins/host.d.ts +34 -0
- package/dist/runtime-plugins/host.js +263 -0
- package/dist/runtime-plugins/host.js.map +1 -0
- package/dist/runtime-plugins/index.d.ts +12 -0
- package/dist/runtime-plugins/index.js +7 -0
- package/dist/runtime-plugins/index.js.map +1 -0
- package/dist/runtime-plugins/loader.d.ts +5 -0
- package/dist/runtime-plugins/loader.js +36 -0
- package/dist/runtime-plugins/loader.js.map +1 -0
- package/dist/runtime-plugins/tool-adapter.d.ts +3 -0
- package/dist/runtime-plugins/tool-adapter.js +13 -0
- package/dist/runtime-plugins/tool-adapter.js.map +1 -0
- package/dist/runtime-plugins/types.d.ts +81 -0
- package/dist/runtime-plugins/types.js +2 -0
- package/dist/runtime-plugins/types.js.map +1 -0
- package/dist/sync/settings.d.ts +2 -0
- package/dist/sync/settings.js +17 -1
- package/dist/sync/settings.js.map +1 -1
- package/dist/tools/registry.d.ts +2 -0
- package/dist/tools/registry.js +10 -0
- package/dist/tools/registry.js.map +1 -1
- package/dist/tools/types.d.ts +2 -0
- package/dist/tools/types.js.map +1 -1
- package/official.json +1 -2
- package/package.json +1 -1
|
@@ -1,282 +1,172 @@
|
|
|
1
1
|
import { readFileSync } from "node:fs";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { fileURLToPath } from "node:url";
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
*/
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
function
|
|
4
|
+
import { readUserFile } from "../../config-files.js";
|
|
5
|
+
/** Client knows the OHarness service, not its database/auth vendor. */
|
|
6
|
+
export function siteUrl() {
|
|
7
|
+
const cloud = readUserFile("cloud.json");
|
|
8
|
+
const legacy = cloud === undefined ? readUserFile("config.json")?.account : undefined;
|
|
9
|
+
let packaged = {};
|
|
10
|
+
try {
|
|
11
|
+
const here = path.dirname(fileURLToPath(import.meta.url));
|
|
12
|
+
packaged = JSON.parse(readFileSync(path.resolve(here, "..", "..", "..", "official.json"), "utf8"));
|
|
13
|
+
}
|
|
14
|
+
catch { /* Optional deployment file; no Supabase credentials are consumed. */ }
|
|
15
|
+
return validateSiteUrl(process.env["OHARNESS_SITE_URL"] || cloud?.siteUrl || legacy?.siteUrl || process.env["OHARNESS_PACKAGED_SITE_URL"] || packaged?.siteUrl || "https://oharness.ai");
|
|
16
|
+
}
|
|
17
|
+
function validateSiteUrl(value) {
|
|
18
|
+
let url;
|
|
18
19
|
try {
|
|
19
|
-
|
|
20
|
-
return parsed.ok ? parsed.value : {};
|
|
20
|
+
url = new URL(value);
|
|
21
21
|
}
|
|
22
22
|
catch {
|
|
23
|
-
|
|
24
|
-
// business to complain about.
|
|
25
|
-
return {};
|
|
23
|
+
throw new Error("Invalid OHarness Cloud address");
|
|
26
24
|
}
|
|
25
|
+
const local = ["localhost", "127.0.0.1", "[::1]"].includes(url.hostname);
|
|
26
|
+
if ((url.protocol !== "https:" && !(url.protocol === "http:" && local)) || url.username || url.password ||
|
|
27
|
+
url.search || url.hash || url.pathname !== "/")
|
|
28
|
+
throw new Error("Cloud address must be an HTTPS origin (HTTP allowed for loopback development)");
|
|
29
|
+
return url.origin;
|
|
27
30
|
}
|
|
28
|
-
/**
|
|
29
|
-
function fromPackage() {
|
|
30
|
-
if (packaged)
|
|
31
|
-
return packaged;
|
|
32
|
-
const here = path.dirname(fileURLToPath(import.meta.url));
|
|
33
|
-
packaged = readJsonFile(path.resolve(here, "..", "..", "..", "official.json"));
|
|
34
|
-
return packaged;
|
|
35
|
-
}
|
|
36
|
-
/** The `account` section of the user's own config file. */
|
|
37
|
-
function fromUserConfig() {
|
|
38
|
-
if (configured)
|
|
39
|
-
return configured;
|
|
40
|
-
const file = readJsonFile(userPath("config.json"));
|
|
41
|
-
configured = file.account ?? {};
|
|
42
|
-
return configured;
|
|
43
|
-
}
|
|
44
|
-
function configuredUrl() {
|
|
45
|
-
const value = process.env["OHARNESS_SUPABASE_URL"] ||
|
|
46
|
-
fromUserConfig().supabaseUrl ||
|
|
47
|
-
fromPackage().supabaseUrl ||
|
|
48
|
-
"";
|
|
49
|
-
return value.replace(/\/+$/, "");
|
|
50
|
-
}
|
|
51
|
-
function configuredKey() {
|
|
52
|
-
return (process.env["OHARNESS_SUPABASE_ANON_KEY"] ||
|
|
53
|
-
fromUserConfig().supabaseAnonKey ||
|
|
54
|
-
fromPackage().supabaseAnonKey ||
|
|
55
|
-
"");
|
|
56
|
-
}
|
|
57
|
-
/** Whether this build knows an account project to talk to at all. */
|
|
31
|
+
/** Configuration readiness, not a network health check. */
|
|
58
32
|
export function accountsConfigured() {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
export function supabaseUrl() {
|
|
66
|
-
const url = configuredUrl();
|
|
67
|
-
if (!url)
|
|
68
|
-
throw new Error(NO_ACCOUNTS);
|
|
69
|
-
return url;
|
|
70
|
-
}
|
|
71
|
-
/**
|
|
72
|
-
* The OHarness site — where accounts are made, paid for, and signed into.
|
|
73
|
-
*
|
|
74
|
-
* A deployment moves it the same way it moves the gateway, and a local `next
|
|
75
|
-
* dev` on port 4000 is the reason this is not a constant.
|
|
76
|
-
*/
|
|
77
|
-
const DEFAULT_SITE_URL = "https://oharness.ai";
|
|
78
|
-
export function siteUrl() {
|
|
79
|
-
// Same order as the project ids above, and it has to be: the browser sign-in
|
|
80
|
-
// hands a session back from whichever site owns those accounts, so a fork
|
|
81
|
-
// that moved the project and not the site would send people to ours to sign
|
|
82
|
-
// in to theirs.
|
|
83
|
-
const value = process.env["OHARNESS_SITE_URL"] ||
|
|
84
|
-
fromUserConfig().siteUrl ||
|
|
85
|
-
fromPackage().siteUrl ||
|
|
86
|
-
DEFAULT_SITE_URL;
|
|
87
|
-
return value.replace(/\/+$/, "");
|
|
33
|
+
try {
|
|
34
|
+
return Boolean(siteUrl());
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
88
39
|
}
|
|
89
|
-
/**
|
|
90
|
-
* Signing in by sending the user to the site, in their own browser.
|
|
91
|
-
*
|
|
92
|
-
* The emailed code below works from anywhere, which is why it is still here —
|
|
93
|
-
* a terminal over SSH has no browser to open. But on a machine that does have
|
|
94
|
-
* one, sending them to the site's own login is strictly better: it is the page
|
|
95
|
-
* that offers a password and Google, it is the page that knows how to sign
|
|
96
|
-
* someone *up*, and neither of those has to be reimplemented here to stay
|
|
97
|
-
* working.
|
|
98
|
-
*
|
|
99
|
-
* What comes back is a sealed code on a loopback redirect, traded for the
|
|
100
|
-
* session over HTTPS. The frontend owns the loopback listener because it is
|
|
101
|
-
* the one already running a local server; this pair of functions is the part
|
|
102
|
-
* that belongs to the account rather than to any one frontend.
|
|
103
|
-
*/
|
|
104
40
|
export function browserSignInUrl(opts) {
|
|
105
|
-
const url = new URL("/auth/desktop",
|
|
41
|
+
const url = new URL("/auth/desktop", siteUrl());
|
|
106
42
|
url.searchParams.set("state", opts.state);
|
|
107
43
|
url.searchParams.set("redirect_uri", opts.redirectUri);
|
|
108
44
|
if (opts.locale)
|
|
109
45
|
url.searchParams.set("locale", opts.locale);
|
|
110
46
|
return url.toString();
|
|
111
47
|
}
|
|
112
|
-
|
|
113
|
-
|
|
48
|
+
export function browserKeyUrl(opts) {
|
|
49
|
+
const url = new URL(browserSignInUrl(opts));
|
|
50
|
+
url.searchParams.set("intent", "key");
|
|
51
|
+
return url.toString();
|
|
52
|
+
}
|
|
53
|
+
/** Native-server request: no browser cookies, redirects or automatic retries. */
|
|
54
|
+
async function cloudPost(origin, route, body) {
|
|
114
55
|
let response;
|
|
115
56
|
try {
|
|
116
|
-
response = await fetch(
|
|
117
|
-
method: "POST",
|
|
57
|
+
response = await fetch(origin + route, {
|
|
58
|
+
method: "POST", redirect: "error", signal: AbortSignal.timeout(20_000),
|
|
118
59
|
headers: { "content-type": "application/json", accept: "application/json" },
|
|
119
|
-
body: JSON.stringify(
|
|
60
|
+
body: JSON.stringify(body),
|
|
120
61
|
});
|
|
121
62
|
}
|
|
122
|
-
catch
|
|
123
|
-
|
|
124
|
-
// OHARNESS_SITE_URL pointing at a dev server that is not running — and it
|
|
125
|
-
// deserves better than "sign-in failed".
|
|
126
|
-
return { type: "failed", error: `could not reach ${siteUrl()}: ${errorMessage(err)}` };
|
|
63
|
+
catch {
|
|
64
|
+
throw new Error("Could not reach OHarness Cloud; check its address and availability");
|
|
127
65
|
}
|
|
128
|
-
const body = parseJson(await response.text());
|
|
129
66
|
if (!response.ok) {
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
};
|
|
67
|
+
await response.body?.cancel();
|
|
68
|
+
const hint = response.status === 404 ? "; update OHarness Cloud to support desktop authentication" : "";
|
|
69
|
+
throw new Error("OHarness Cloud authentication failed (HTTP " + response.status + ")" + hint);
|
|
134
70
|
}
|
|
135
|
-
|
|
136
|
-
|
|
71
|
+
const reader = response.body?.getReader();
|
|
72
|
+
if (!reader)
|
|
73
|
+
throw new Error("OHarness Cloud returned an empty response");
|
|
74
|
+
const chunks = [];
|
|
75
|
+
let size = 0;
|
|
76
|
+
try {
|
|
77
|
+
while (true) {
|
|
78
|
+
const { done, value } = await reader.read();
|
|
79
|
+
if (done)
|
|
80
|
+
break;
|
|
81
|
+
size += value.byteLength;
|
|
82
|
+
if (size > 64 * 1024) {
|
|
83
|
+
await reader.cancel();
|
|
84
|
+
throw new Error("Response too large");
|
|
85
|
+
}
|
|
86
|
+
chunks.push(value);
|
|
87
|
+
}
|
|
88
|
+
const result = JSON.parse(Buffer.concat(chunks).toString("utf8"));
|
|
89
|
+
if (!result || typeof result !== "object" || Array.isArray(result))
|
|
90
|
+
throw new Error();
|
|
91
|
+
return result;
|
|
92
|
+
}
|
|
93
|
+
catch {
|
|
94
|
+
throw new Error("OHarness Cloud returned an invalid authentication response");
|
|
95
|
+
}
|
|
96
|
+
finally {
|
|
97
|
+
reader.releaseLock();
|
|
137
98
|
}
|
|
138
|
-
return {
|
|
139
|
-
type: "success",
|
|
140
|
-
access: body.value.access_token,
|
|
141
|
-
refresh: body.value.refresh_token,
|
|
142
|
-
expires: body.value.expires_at ?? 0,
|
|
143
|
-
};
|
|
144
|
-
}
|
|
145
|
-
function supabaseKey() {
|
|
146
|
-
const key = configuredKey();
|
|
147
|
-
if (!key)
|
|
148
|
-
throw new Error(NO_ACCOUNTS);
|
|
149
|
-
return key;
|
|
150
99
|
}
|
|
151
|
-
/**
|
|
152
|
-
|
|
100
|
+
/** Epoch milliseconds, matching the existing desktop exchange contract. */
|
|
101
|
+
function sessionCredential(data, origin, previous) {
|
|
102
|
+
if (typeof data.access_token !== "string" || !data.access_token ||
|
|
103
|
+
typeof data.refresh_token !== "string" || !data.refresh_token ||
|
|
104
|
+
typeof data.expires_at !== "number" || !Number.isFinite(data.expires_at) || data.expires_at <= 0) {
|
|
105
|
+
throw new Error("OHarness Cloud returned an incomplete session");
|
|
106
|
+
}
|
|
153
107
|
return {
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
accept: "application/json",
|
|
108
|
+
...previous, type: "oauth", access: data.access_token, refresh: data.refresh_token,
|
|
109
|
+
expires: data.expires_at, metadata: { ...previous?.metadata, cloudOrigin: origin },
|
|
157
110
|
};
|
|
158
111
|
}
|
|
159
|
-
|
|
112
|
+
export async function exchangeHandoff(code, state) {
|
|
113
|
+
try {
|
|
114
|
+
const origin = siteUrl();
|
|
115
|
+
const data = await cloudPost(origin, "/api/desktop/exchange", { code, state });
|
|
116
|
+
if (typeof data.api_key === "string" && data.api_key) {
|
|
117
|
+
const metadata = {};
|
|
118
|
+
if (typeof data.prefix === "string")
|
|
119
|
+
metadata.prefix = data.prefix;
|
|
120
|
+
if (typeof data.name === "string")
|
|
121
|
+
metadata.name = data.name;
|
|
122
|
+
return { type: "success", key: data.api_key, metadata };
|
|
123
|
+
}
|
|
124
|
+
const { type: _, ...credential } = sessionCredential(data, origin);
|
|
125
|
+
return { type: "success", ...credential };
|
|
126
|
+
}
|
|
127
|
+
catch (error) {
|
|
128
|
+
return { type: "failed", error: error.message };
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
/** SSH/terminal fallback. The legacy code flow now also goes through Cloud. */
|
|
160
132
|
export function accountSignIn(label) {
|
|
161
133
|
return {
|
|
162
|
-
type: "oauth",
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
{
|
|
166
|
-
type: "text",
|
|
167
|
-
key: "email",
|
|
168
|
-
message: "Email on your OHarness account",
|
|
169
|
-
placeholder: "you@example.com",
|
|
170
|
-
validate: (value) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value) ? undefined : "that does not look like an email",
|
|
171
|
-
},
|
|
172
|
-
],
|
|
134
|
+
type: "oauth", label,
|
|
135
|
+
prompts: [{ type: "text", key: "email", message: "Email on your OHarness account", placeholder: "you@example.com",
|
|
136
|
+
validate: (value) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value) ? undefined : "Enter an email address" }],
|
|
173
137
|
async authorize(inputs) {
|
|
174
|
-
const email = (inputs
|
|
175
|
-
const
|
|
176
|
-
|
|
177
|
-
headers: supabaseHeaders(),
|
|
178
|
-
// Signing up is the website's job: a subscription has to be paid for
|
|
179
|
-
// before it can be signed into, and silently creating an account
|
|
180
|
-
// here would hand out a login that cannot call anything.
|
|
181
|
-
body: JSON.stringify({ email, create_user: false }),
|
|
182
|
-
});
|
|
183
|
-
if (!response.ok) {
|
|
184
|
-
const detail = await failureDetail(response);
|
|
185
|
-
// GoTrue phrases "this address has no account" as a signup refusal,
|
|
186
|
-
// which reads as a bug in the client to anyone who does have one.
|
|
187
|
-
const noAccount = /signups? not allowed/i.test(detail);
|
|
188
|
-
throw new Error(noAccount
|
|
189
|
-
? `no OHarness account for ${email}. Sign up on the OHarness site first, then sign in here.`
|
|
190
|
-
: `could not send the sign-in code to ${email}: ${detail}`);
|
|
191
|
-
}
|
|
138
|
+
const email = (inputs.email ?? "").trim();
|
|
139
|
+
const origin = siteUrl();
|
|
140
|
+
await cloudPost(origin, "/api/desktop/auth/otp", { email });
|
|
192
141
|
return {
|
|
193
|
-
method: "code",
|
|
194
|
-
|
|
195
|
-
// No page to open: the code arrives by email, and sending a browser
|
|
196
|
-
// to the login form would only invite a second, competing session.
|
|
197
|
-
async callback(code) {
|
|
198
|
-
try {
|
|
199
|
-
return await verifyOtp(email, code);
|
|
200
|
-
}
|
|
201
|
-
catch (err) {
|
|
202
|
-
return { type: "failed", error: errorMessage(err) };
|
|
203
|
-
}
|
|
204
|
-
},
|
|
142
|
+
method: "code", instructions: "Check " + email + " for your sign-in code.",
|
|
143
|
+
callback: (code) => verifyOtp(email, code, origin),
|
|
205
144
|
};
|
|
206
145
|
},
|
|
207
146
|
};
|
|
208
147
|
}
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
body: JSON.stringify({ email, token: code.trim(), type: "email" }),
|
|
215
|
-
});
|
|
216
|
-
if (!response.ok) {
|
|
217
|
-
return { type: "failed", error: await failureDetail(response) };
|
|
148
|
+
export async function verifyOtp(email, code, origin = siteUrl()) {
|
|
149
|
+
try {
|
|
150
|
+
const data = await cloudPost(validateSiteUrl(origin), "/api/desktop/auth/verify", { email, token: code.trim() });
|
|
151
|
+
const { type: _, ...credential } = sessionCredential(data, origin);
|
|
152
|
+
return { type: "success", ...credential };
|
|
218
153
|
}
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
return { type: "failed", error: "the sign-in returned no access token" };
|
|
154
|
+
catch (error) {
|
|
155
|
+
return { type: "failed", error: error.message };
|
|
222
156
|
}
|
|
223
|
-
const credential = toCredential(session.value);
|
|
224
|
-
return {
|
|
225
|
-
type: "success",
|
|
226
|
-
access: credential.access,
|
|
227
|
-
refresh: credential.refresh,
|
|
228
|
-
expires: credential.expires,
|
|
229
|
-
};
|
|
230
157
|
}
|
|
231
|
-
/** Trade a refresh token for a fresh session, or nothing if it is still good. */
|
|
232
158
|
export async function refreshSession(credential) {
|
|
233
159
|
if (!credential.refresh)
|
|
234
160
|
return undefined;
|
|
235
|
-
|
|
236
|
-
//
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
headers: supabaseHeaders(),
|
|
240
|
-
body: JSON.stringify({ refresh_token: credential.refresh }),
|
|
241
|
-
});
|
|
242
|
-
if (!response.ok) {
|
|
243
|
-
throw new Error(`subscription refresh failed: ${await failureDetail(response)}`);
|
|
161
|
+
const origin = siteUrl();
|
|
162
|
+
// Never forward a credential to another deployment after a config change.
|
|
163
|
+
if (credential.metadata?.cloudOrigin && credential.metadata.cloudOrigin !== origin) {
|
|
164
|
+
throw new Error("Cloud address changed; sign in again before refreshing this account");
|
|
244
165
|
}
|
|
245
|
-
const
|
|
246
|
-
|
|
247
|
-
throw new Error("subscription refresh returned no access token");
|
|
248
|
-
}
|
|
249
|
-
return toCredential(session.value, credential);
|
|
250
|
-
}
|
|
251
|
-
export function toCredential(session, previous) {
|
|
252
|
-
return {
|
|
253
|
-
type: "oauth",
|
|
254
|
-
access: session.access_token,
|
|
255
|
-
// GoTrue rotates the refresh token on every use, but keep the previous one
|
|
256
|
-
// if a response ever omits it — dropping it ends the session at expiry.
|
|
257
|
-
refresh: session.refresh_token ?? previous?.refresh ?? "",
|
|
258
|
-
expires: session.expires_in ? Date.now() + session.expires_in * 1_000 : 0,
|
|
259
|
-
...(previous?.baseUrl ? { baseUrl: previous.baseUrl } : {}),
|
|
260
|
-
};
|
|
261
|
-
}
|
|
262
|
-
/**
|
|
263
|
-
* GoTrue reports failures under several field names depending on the version
|
|
264
|
-
* and the error class. Probing them beats showing a bare status code, which is
|
|
265
|
-
* what "sign-in failed (400)" leaves the user debugging.
|
|
266
|
-
*/
|
|
267
|
-
export async function failureDetail(response) {
|
|
268
|
-
const text = await response.text();
|
|
269
|
-
const parsed = parseJson(text);
|
|
270
|
-
const detail = parsed.ok
|
|
271
|
-
? (parsed.value.error_description ??
|
|
272
|
-
parsed.value.msg ??
|
|
273
|
-
parsed.value.message ??
|
|
274
|
-
parsed.value.error)
|
|
275
|
-
: undefined;
|
|
276
|
-
return `HTTP ${response.status}${detail ? `: ${detail}` : ` ${text.slice(0, 200)}`}`;
|
|
166
|
+
const data = await cloudPost(origin, "/api/desktop/auth/refresh", { refresh_token: credential.refresh });
|
|
167
|
+
return sessionCredential(data, origin, credential);
|
|
277
168
|
}
|
|
278
|
-
/** The bearer shape both account-backed providers resolve to. */
|
|
279
169
|
export function bearer(token, source) {
|
|
280
|
-
return { headers: { authorization:
|
|
170
|
+
return { headers: { authorization: "Bearer " + token }, source };
|
|
281
171
|
}
|
|
282
172
|
//# sourceMappingURL=account.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"account.js","sourceRoot":"","sources":["../../../src/auth/providers/account.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"account.js","sourceRoot":"","sources":["../../../src/auth/providers/account.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { McpServerConfig } from "./mcp/client.ts";
|
|
2
|
+
import type { RuntimePluginConfig } from "./runtime-plugins/types.ts";
|
|
3
|
+
import type { PluginConfig } from "./plugins.ts";
|
|
4
|
+
export interface PluginFile {
|
|
5
|
+
runtimePlugins?: RuntimePluginConfig[];
|
|
6
|
+
plugins?: PluginConfig;
|
|
7
|
+
}
|
|
8
|
+
export interface McpFile {
|
|
9
|
+
mcpServers?: Record<string, McpServerConfig>;
|
|
10
|
+
}
|
|
11
|
+
export interface CloudFile {
|
|
12
|
+
siteUrl?: string;
|
|
13
|
+
}
|
|
14
|
+
/** Read only trusted user files, never a repository's executable plugin list. */
|
|
15
|
+
export declare function readUserFile<T extends object>(name: string): T | undefined;
|
|
16
|
+
export declare function readPluginFile(): PluginFile | undefined;
|
|
17
|
+
export declare function readMcpFile(): McpFile | undefined;
|
|
18
|
+
/** Atomic private files; no credentials/config values in error messages. */
|
|
19
|
+
export declare function writeUserFile(name: string, data: object): Promise<void>;
|
|
20
|
+
export declare function updateRuntimePluginConfig(id: string, change: (config: Record<string, unknown>) => Record<string, unknown>): Promise<void>;
|
|
21
|
+
export declare function updateUserMcpConfig(change: (servers: Record<string, McpServerConfig>) => Record<string, McpServerConfig>): Promise<void>;
|
|
22
|
+
/** An explicit migration, not a startup side effect. Back up before removing old fields. */
|
|
23
|
+
export declare function migrateUserConfig(apply?: boolean): Promise<{
|
|
24
|
+
changed: boolean;
|
|
25
|
+
files: string[];
|
|
26
|
+
backup?: string;
|
|
27
|
+
}>;
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
import { mkdir, writeFile, rename, rm } from "node:fs/promises";
|
|
3
|
+
import { randomUUID } from "node:crypto";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import { userPath } from "./paths.js";
|
|
6
|
+
import { ConfigError } from "./core/errors.js";
|
|
7
|
+
/** Read only trusted user files, never a repository's executable plugin list. */
|
|
8
|
+
export function readUserFile(name) {
|
|
9
|
+
const file = userPath(name);
|
|
10
|
+
let raw;
|
|
11
|
+
try {
|
|
12
|
+
raw = readFileSync(file, "utf8");
|
|
13
|
+
}
|
|
14
|
+
catch (error) {
|
|
15
|
+
if (error.code === "ENOENT")
|
|
16
|
+
return undefined;
|
|
17
|
+
throw new ConfigError(`Cannot read ${file}`);
|
|
18
|
+
}
|
|
19
|
+
try {
|
|
20
|
+
const data = JSON.parse(raw);
|
|
21
|
+
if (!data || typeof data !== "object" || Array.isArray(data))
|
|
22
|
+
throw new Error();
|
|
23
|
+
return data;
|
|
24
|
+
}
|
|
25
|
+
catch {
|
|
26
|
+
throw new ConfigError(`${file} must contain a JSON object`);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
export function readPluginFile() {
|
|
30
|
+
const config = readUserFile("plugins.json");
|
|
31
|
+
if (config?.runtimePlugins !== undefined && !Array.isArray(config.runtimePlugins)) {
|
|
32
|
+
throw new ConfigError("plugins.json runtimePlugins must be an array");
|
|
33
|
+
}
|
|
34
|
+
return config;
|
|
35
|
+
}
|
|
36
|
+
export function readMcpFile() {
|
|
37
|
+
const config = readUserFile("mcp.json");
|
|
38
|
+
if (config?.mcpServers !== undefined && (!config.mcpServers || typeof config.mcpServers !== "object" || Array.isArray(config.mcpServers))) {
|
|
39
|
+
throw new ConfigError("mcp.json mcpServers must be an object");
|
|
40
|
+
}
|
|
41
|
+
return config;
|
|
42
|
+
}
|
|
43
|
+
/** Atomic private files; no credentials/config values in error messages. */
|
|
44
|
+
export async function writeUserFile(name, data) {
|
|
45
|
+
const file = userPath(name);
|
|
46
|
+
await mkdir(path.dirname(file), { recursive: true });
|
|
47
|
+
const temp = `${file}.${randomUUID()}.tmp`;
|
|
48
|
+
try {
|
|
49
|
+
await writeFile(temp, JSON.stringify(data, null, 2) + "\n", { mode: 0o600, flag: "wx" });
|
|
50
|
+
await rename(temp, file);
|
|
51
|
+
}
|
|
52
|
+
finally {
|
|
53
|
+
await rm(temp, { force: true });
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
let mcpWriteQueue = Promise.resolve();
|
|
57
|
+
let pluginWriteQueue = Promise.resolve();
|
|
58
|
+
export function updateRuntimePluginConfig(id, change) {
|
|
59
|
+
const job = pluginWriteQueue.then(async () => {
|
|
60
|
+
const separate = readPluginFile();
|
|
61
|
+
const previous = separate ?? readUserFile("config.json") ?? {};
|
|
62
|
+
const entries = [...(previous.runtimePlugins ?? [])];
|
|
63
|
+
const index = entries.findIndex((entry) => entry.id === id);
|
|
64
|
+
const entry = entries[index] ?? { id };
|
|
65
|
+
const raw = entry.config && typeof entry.config === "object" && !Array.isArray(entry.config) ? entry.config : {};
|
|
66
|
+
const next = { ...entry, config: change(raw) };
|
|
67
|
+
if (index >= 0)
|
|
68
|
+
entries[index] = next;
|
|
69
|
+
else
|
|
70
|
+
entries.push(next);
|
|
71
|
+
await writeUserFile("plugins.json", { ...(separate ?? {}), ...(previous.plugins ? { plugins: previous.plugins } : {}), runtimePlugins: entries });
|
|
72
|
+
});
|
|
73
|
+
pluginWriteQueue = job.catch(() => { });
|
|
74
|
+
return job;
|
|
75
|
+
}
|
|
76
|
+
export function updateUserMcpConfig(change) {
|
|
77
|
+
const job = mcpWriteQueue.then(async () => {
|
|
78
|
+
const separate = readMcpFile();
|
|
79
|
+
const old = separate === undefined ? readUserFile("config.json") : undefined;
|
|
80
|
+
await writeUserFile("mcp.json", { ...separate, mcpServers: change({ ...(separate?.mcpServers ?? old?.mcpServers) }) });
|
|
81
|
+
});
|
|
82
|
+
mcpWriteQueue = job.catch(() => { });
|
|
83
|
+
return job;
|
|
84
|
+
}
|
|
85
|
+
/** An explicit migration, not a startup side effect. Back up before removing old fields. */
|
|
86
|
+
export async function migrateUserConfig(apply = false) {
|
|
87
|
+
const current = readUserFile("config.json");
|
|
88
|
+
if (!current || !["account", "mcpServers", "runtimePlugins", "plugins"].some((key) => key in current)) {
|
|
89
|
+
return { changed: false, files: [] };
|
|
90
|
+
}
|
|
91
|
+
// Validate destinations before changing anything; existing files are authoritative.
|
|
92
|
+
const plugins = readPluginFile();
|
|
93
|
+
const mcp = readMcpFile();
|
|
94
|
+
const cloud = readUserFile("cloud.json");
|
|
95
|
+
const { account, mcpServers, runtimePlugins, plugins: bundles, ...general } = current;
|
|
96
|
+
const outputs = {};
|
|
97
|
+
if (!plugins) {
|
|
98
|
+
outputs["plugins.json"] = { runtimePlugins: runtimePlugins ?? [], ...(bundles !== undefined ? { plugins: bundles } : {}) };
|
|
99
|
+
}
|
|
100
|
+
if (!mcp && mcpServers !== undefined)
|
|
101
|
+
outputs["mcp.json"] = { mcpServers };
|
|
102
|
+
const site = account && typeof account === "object" ? account.siteUrl : undefined;
|
|
103
|
+
if (!cloud && typeof site === "string" && site)
|
|
104
|
+
outputs["cloud.json"] = { siteUrl: site };
|
|
105
|
+
outputs["config.json"] = general;
|
|
106
|
+
const files = Object.keys(outputs).map((name) => userPath(name));
|
|
107
|
+
if (!apply)
|
|
108
|
+
return { changed: true, files };
|
|
109
|
+
const backup = `config.before-split.${randomUUID()}.json`;
|
|
110
|
+
await writeUserFile(backup, current);
|
|
111
|
+
// Write config.json last. A crash leaves the legacy source intact and is retryable.
|
|
112
|
+
for (const [name, data] of Object.entries(outputs))
|
|
113
|
+
await writeUserFile(name, data);
|
|
114
|
+
return { changed: true, files, backup: userPath(backup) };
|
|
115
|
+
}
|
|
116
|
+
//# sourceMappingURL=config-files.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config-files.js","sourceRoot":"","sources":["../src/config-files.ts"],"names":[],"mappings":"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"}
|