shadow-claw 1.23.3 → 1.23.4
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/bin/assert-version-bump.mjs +60 -38
- package/bin/assert-version-bump.test.mjs +74 -11
- package/dist/public/agent.worker.js +6 -6
- package/dist/public/{app-routes-B0ePT49v.js → app-routes-Bs-riIvr.js} +1 -1
- package/dist/public/components/settings/shadow-claw-storage/shadow-claw-storage.html +1 -1
- package/dist/public/components/shadow-claw-files/shadow-claw-files.css +1 -1
- package/dist/public/components/shadow-claw-files/shadow-claw-files.html +1 -1
- package/dist/public/config-BYAuxx3j.js +1 -0
- package/dist/public/{configurePeerJs-B7kNU8AQ.js → configurePeerJs-B4Ym9VMj.js} +1 -1
- package/dist/public/{connections-xd_66YVU.js → connections-BEn6JYdu.js} +1 -1
- package/dist/public/{custom-element-security-CZ92anB8.js → custom-element-security-DdYlUozq.js} +1 -1
- package/dist/public/docs/architecture/storage.md +5 -2
- package/dist/public/docs/decisions/indexeddb-and-opfs-storage.md +5 -2
- package/dist/public/docs/example/article/index.html +2 -2
- package/dist/public/docs/publishing/index.html +19 -76
- package/dist/public/docs/skill-creator/index.html +2 -2
- package/dist/public/{downloadGroupFile-BABv_1mJ.js → downloadGroupFile-Drdvg1Ev.js} +1 -1
- package/dist/public/{e2e-bridge-DkS5xFGX.js → e2e-bridge-BQ4KzUt5.js} +1 -1
- package/dist/public/{file-viewer-CCSABMsE.js → file-viewer-CcZYw-PS.js} +1 -1
- package/dist/public/files/main/~/docs/publishing-to-github-pages.md +17 -82
- package/dist/public/{git-BkjrsRXX.js → git-DEUvQTUA.js} +2 -2
- package/dist/public/{iframe-sanitizer-L6Jyu__Z.js → iframe-sanitizer-0NS4XLOd.js} +1 -1
- package/dist/public/index.html +2 -2
- package/dist/public/index.js +1 -1
- package/dist/public/{initChatSplitResize-BslPXAXS.js → initChatSplitResize-llGkSJXg.js} +1 -1
- package/dist/public/main/index.html +2 -2
- package/dist/public/main/memory/index.html +2 -2
- package/dist/public/{markdown-6MBrIo-S.js → markdown-CyYR4App.js} +1 -1
- package/dist/public/mcp-reconnect-CSx4aMwy.js +1 -0
- package/dist/public/{memoryStorage-CjGseKI1.js → memoryStorage-Dwg8NhAZ.js} +1 -1
- package/dist/public/{orchestrator-B9KmIj8Q.js → orchestrator-DRfEudXk.js} +18 -18
- package/dist/public/orchestrator-o9Fj67BN.js +15 -0
- package/dist/public/pages/main/~/docs/publishing-to-github-pages.md +17 -82
- package/dist/public/{peerjs-Dv8JNm7v.js → peerjs-CurBuKvk.js} +1 -1
- package/dist/public/{push-client-Dqq06wbB.js → push-client-Dii-vPEh.js} +1 -1
- package/dist/public/service-worker/fetch-proxy.js +1 -1
- package/dist/public/service-worker.js +1 -1
- package/dist/public/{shadow-claw-Bd1rfuVC.js → shadow-claw-5IHaDDMJ.js} +2 -2
- package/dist/public/{shadow-claw-accounts-DL2l3oM0.js → shadow-claw-accounts-CZvz4iQz.js} +3 -3
- package/dist/public/{shadow-claw-channels-BGXDsQ38.js → shadow-claw-channels-BKXFyRS3.js} +1 -1
- package/dist/public/{shadow-claw-chat-NXg6zz_l.js → shadow-claw-chat-CCLuhWdI.js} +3 -3
- package/dist/public/{shadow-claw-conversations-C8eqGpP9.js → shadow-claw-conversations-DV-87UUh.js} +1 -1
- package/dist/public/shadow-claw-file-viewer-Dk2dbAUd.js +577 -0
- package/dist/public/shadow-claw-files-BpfpJIuP.js +840 -0
- package/dist/public/{shadow-claw-git-C0ntz7aX.js → shadow-claw-git-DRA7_qck.js} +3 -3
- package/dist/public/{shadow-claw-integrations-DCXV2r69.js → shadow-claw-integrations-1Xu5snuV.js} +1 -1
- package/dist/public/{shadow-claw-llm-CudgFQsS.js → shadow-claw-llm-6Aci1BDP.js} +2 -2
- package/dist/public/{shadow-claw-mcp-remote-B8RkpX28.js → shadow-claw-mcp-remote-BUjAeVXC.js} +1 -1
- package/dist/public/{shadow-claw-networking-BLiRsrsK.js → shadow-claw-networking-FQe4nCp3.js} +1 -1
- package/dist/public/{shadow-claw-notifications-CQhQcjtL.js → shadow-claw-notifications-DV2wibL3.js} +1 -1
- package/dist/public/{shadow-claw-page-header-NeRD0tKU.js → shadow-claw-page-header-B63S4HTU.js} +1 -1
- package/dist/public/{shadow-claw-pages-DCHnFh6r.js → shadow-claw-pages-DE3jWj5K.js} +3 -3
- package/dist/public/{shadow-claw-settings-VAfjKFQg.js → shadow-claw-settings-S6DAKfYx.js} +3 -3
- package/dist/public/shadow-claw-storage-DaacA3_K.js +219 -0
- package/dist/public/{shadow-claw-task-server-Dk33N_1G.js → shadow-claw-task-server-IjKX042p.js} +1 -1
- package/dist/public/{shadow-claw-tasks-xA1VfmWN.js → shadow-claw-tasks-Cy0JYmGU.js} +4 -4
- package/dist/public/{shadow-claw-terminal-Du2r0ciq.js → shadow-claw-terminal-znAt7HyP.js} +1 -1
- package/dist/public/{shadow-claw-tools-CZj4rq7l.js → shadow-claw-tools-Cutv9Si5.js} +2 -2
- package/dist/public/{shadow-claw-webvm-JYUkWICG.js → shadow-claw-webvm-BH8mPDEu.js} +1 -1
- package/dist/public/static-main/~/docs/publishing-to-github-pages.md +17 -82
- package/dist/public/static-main-manifest.json +1 -1
- package/dist/public/{syncWebMcpRegistration-DfpvASnh.js → syncWebMcpRegistration-BqJxaMGR.js} +1 -1
- package/package.json +1 -1
- package/src/components/settings/shadow-claw-storage/shadow-claw-storage.html +17 -0
- package/src/components/settings/shadow-claw-storage/shadow-claw-storage.test.ts +44 -0
- package/src/components/settings/shadow-claw-storage/shadow-claw-storage.ts +56 -0
- package/src/components/shadow-claw-file-viewer/shadow-claw-file-viewer.test.ts +105 -0
- package/src/components/shadow-claw-file-viewer/shadow-claw-file-viewer.ts +11 -9
- package/src/components/shadow-claw-files/shadow-claw-files.css +41 -17
- package/src/components/shadow-claw-files/shadow-claw-files.html +35 -0
- package/src/components/shadow-claw-files/shadow-claw-files.test.ts +219 -0
- package/src/components/shadow-claw-files/shadow-claw-files.ts +170 -6
- package/src/components/shadow-claw-pages/utils/resolveWorkspaceLinkPath.test.ts +31 -0
- package/src/components/shadow-claw-pages/utils/resolveWorkspaceLinkPath.ts +2 -1
- package/src/components/shadow-claw-pages/utils/rewriteWorkspacePreviewHtml.test.ts +15 -0
- package/src/config/config.test.ts +9 -0
- package/src/config/config.ts +5 -0
- package/src/core/app-routes.test.ts +56 -0
- package/src/core/app-routes.ts +8 -1
- package/src/db/openDatabase.test.ts +10 -1
- package/src/db/openDatabase.ts +3 -1
- package/src/storage/migrateLegacyOpfs.test.ts +327 -0
- package/src/storage/migrateLegacyOpfs.ts +117 -0
- package/dist/public/config-AL77QAx4.js +0 -1
- package/dist/public/mcp-reconnect-DoicazQd.js +0 -1
- package/dist/public/orchestrator-4su7iyWj.js +0 -15
- package/dist/public/shadow-claw-file-viewer-9Qkwc30T.js +0 -577
- package/dist/public/shadow-claw-files-aDyq6Hv7.js +0 -781
- package/dist/public/shadow-claw-storage-Cf31np81.js +0 -202
|
@@ -0,0 +1,327 @@
|
|
|
1
|
+
import { jest } from "@jest/globals";
|
|
2
|
+
import { CONFIG_KEYS, LEGACY_OPFS_ROOT } from "../config/config.js";
|
|
3
|
+
import type { ShadowClawDatabase } from "../db/types.js";
|
|
4
|
+
|
|
5
|
+
const mockGetConfig = jest.fn() as any;
|
|
6
|
+
const mockSetConfig = jest.fn() as any;
|
|
7
|
+
const mockGetOpfsRootDirName = jest.fn() as any;
|
|
8
|
+
const mockWriteFileHandle = jest.fn() as any;
|
|
9
|
+
const mockWriteOpfsPathViaWorker = jest.fn() as any;
|
|
10
|
+
|
|
11
|
+
jest.unstable_mockModule("../db/getConfig.js", () => ({
|
|
12
|
+
getConfig: mockGetConfig,
|
|
13
|
+
}));
|
|
14
|
+
|
|
15
|
+
jest.unstable_mockModule("../db/setConfig.js", () => ({
|
|
16
|
+
setConfig: mockSetConfig,
|
|
17
|
+
}));
|
|
18
|
+
|
|
19
|
+
jest.unstable_mockModule("./storage.js", () => ({
|
|
20
|
+
getOpfsRootDirName: mockGetOpfsRootDirName,
|
|
21
|
+
}));
|
|
22
|
+
|
|
23
|
+
jest.unstable_mockModule("./writeFileHandle.js", () => ({
|
|
24
|
+
writeFileHandle: mockWriteFileHandle,
|
|
25
|
+
writeOpfsPathViaWorker: mockWriteOpfsPathViaWorker,
|
|
26
|
+
}));
|
|
27
|
+
|
|
28
|
+
const { migrateLegacyOpfs } = await import("./migrateLegacyOpfs.js");
|
|
29
|
+
|
|
30
|
+
describe("migrateLegacyOpfs", () => {
|
|
31
|
+
const originalNavigator = globalThis.navigator;
|
|
32
|
+
|
|
33
|
+
beforeEach(() => {
|
|
34
|
+
jest.clearAllMocks();
|
|
35
|
+
mockGetConfig.mockResolvedValue(null);
|
|
36
|
+
mockSetConfig.mockResolvedValue(undefined);
|
|
37
|
+
mockGetOpfsRootDirName.mockReturnValue("shadowclaw-shadow-claw");
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
afterEach(() => {
|
|
41
|
+
Object.defineProperty(globalThis, "navigator", {
|
|
42
|
+
value: originalNavigator,
|
|
43
|
+
configurable: true,
|
|
44
|
+
writable: true,
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
it("skips migration if already completed", async () => {
|
|
49
|
+
mockGetConfig.mockResolvedValue("true");
|
|
50
|
+
const mockDb = {} as ShadowClawDatabase;
|
|
51
|
+
|
|
52
|
+
await migrateLegacyOpfs(mockDb);
|
|
53
|
+
|
|
54
|
+
expect(mockGetConfig).toHaveBeenCalledWith(
|
|
55
|
+
mockDb,
|
|
56
|
+
CONFIG_KEYS.OPFS_MIGRATED_FROM_LEGACY,
|
|
57
|
+
);
|
|
58
|
+
expect(mockSetConfig).not.toHaveBeenCalled();
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
it("skips migration if target root is the legacy root", async () => {
|
|
62
|
+
mockGetOpfsRootDirName.mockReturnValue(LEGACY_OPFS_ROOT);
|
|
63
|
+
const mockDb = {} as ShadowClawDatabase;
|
|
64
|
+
|
|
65
|
+
await migrateLegacyOpfs(mockDb);
|
|
66
|
+
|
|
67
|
+
expect(mockSetConfig).not.toHaveBeenCalled();
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
it("handles when navigator.storage is undefined", async () => {
|
|
71
|
+
Object.defineProperty(globalThis, "navigator", {
|
|
72
|
+
value: {},
|
|
73
|
+
configurable: true,
|
|
74
|
+
writable: true,
|
|
75
|
+
});
|
|
76
|
+
const mockDb = {} as ShadowClawDatabase;
|
|
77
|
+
|
|
78
|
+
await expect(migrateLegacyOpfs(mockDb)).resolves.toBeUndefined();
|
|
79
|
+
expect(mockSetConfig).not.toHaveBeenCalled();
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
it("handles when legacy OPFS directory does not exist and sets flag", async () => {
|
|
83
|
+
const mockOpfsRoot: any = {
|
|
84
|
+
getDirectoryHandle: (jest.fn() as any).mockImplementation(
|
|
85
|
+
(name: string) => {
|
|
86
|
+
if (name === LEGACY_OPFS_ROOT) {
|
|
87
|
+
throw new DOMException("Directory not found", "NotFoundError");
|
|
88
|
+
}
|
|
89
|
+
return Promise.resolve({});
|
|
90
|
+
},
|
|
91
|
+
),
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
Object.defineProperty(globalThis, "navigator", {
|
|
95
|
+
value: {
|
|
96
|
+
storage: {
|
|
97
|
+
getDirectory: (jest.fn() as any).mockResolvedValue(mockOpfsRoot),
|
|
98
|
+
},
|
|
99
|
+
},
|
|
100
|
+
configurable: true,
|
|
101
|
+
writable: true,
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
const mockDb = {} as ShadowClawDatabase;
|
|
105
|
+
await migrateLegacyOpfs(mockDb);
|
|
106
|
+
|
|
107
|
+
expect(mockSetConfig).toHaveBeenCalledWith(
|
|
108
|
+
mockDb,
|
|
109
|
+
CONFIG_KEYS.OPFS_MIGRATED_FROM_LEGACY,
|
|
110
|
+
"true",
|
|
111
|
+
);
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
it("recursively copies legacy files and directories into the namespaced target root", async () => {
|
|
115
|
+
const mockFile1 = new File(["notes content"], "note.md", {
|
|
116
|
+
type: "text/markdown",
|
|
117
|
+
});
|
|
118
|
+
const mockFile2 = new File(["memory content"], "MEMORY.md", {
|
|
119
|
+
type: "text/markdown",
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
const mockNotesWorkspaceDir = {
|
|
123
|
+
entries: async function* () {
|
|
124
|
+
yield [
|
|
125
|
+
"note.md",
|
|
126
|
+
{
|
|
127
|
+
kind: "file",
|
|
128
|
+
getFile: jest.fn(async () => mockFile1),
|
|
129
|
+
},
|
|
130
|
+
];
|
|
131
|
+
},
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
const mockNotesGroupDir = {
|
|
135
|
+
entries: async function* () {
|
|
136
|
+
yield [
|
|
137
|
+
"workspace",
|
|
138
|
+
{
|
|
139
|
+
kind: "directory",
|
|
140
|
+
...mockNotesWorkspaceDir,
|
|
141
|
+
},
|
|
142
|
+
];
|
|
143
|
+
},
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
const mockMainWorkspaceDir = {
|
|
147
|
+
entries: async function* () {
|
|
148
|
+
yield [
|
|
149
|
+
"MEMORY.md",
|
|
150
|
+
{
|
|
151
|
+
kind: "file",
|
|
152
|
+
getFile: jest.fn(async () => mockFile2),
|
|
153
|
+
},
|
|
154
|
+
];
|
|
155
|
+
},
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
const mockMainGroupDir = {
|
|
159
|
+
entries: async function* () {
|
|
160
|
+
yield [
|
|
161
|
+
"workspace",
|
|
162
|
+
{
|
|
163
|
+
kind: "directory",
|
|
164
|
+
...mockMainWorkspaceDir,
|
|
165
|
+
},
|
|
166
|
+
];
|
|
167
|
+
},
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
const mockLegacyGroupsDir = {
|
|
171
|
+
entries: async function* () {
|
|
172
|
+
yield [
|
|
173
|
+
"br-notes",
|
|
174
|
+
{
|
|
175
|
+
kind: "directory",
|
|
176
|
+
...mockNotesGroupDir,
|
|
177
|
+
},
|
|
178
|
+
];
|
|
179
|
+
yield [
|
|
180
|
+
"br-main",
|
|
181
|
+
{
|
|
182
|
+
kind: "directory",
|
|
183
|
+
...mockMainGroupDir,
|
|
184
|
+
},
|
|
185
|
+
];
|
|
186
|
+
},
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
const mockLegacyRoot = {
|
|
190
|
+
entries: async function* () {
|
|
191
|
+
yield [
|
|
192
|
+
"groups",
|
|
193
|
+
{
|
|
194
|
+
kind: "directory",
|
|
195
|
+
...mockLegacyGroupsDir,
|
|
196
|
+
},
|
|
197
|
+
];
|
|
198
|
+
},
|
|
199
|
+
};
|
|
200
|
+
|
|
201
|
+
const createdDirs = new Map<string, any>();
|
|
202
|
+
const createdFiles = new Map<string, any>();
|
|
203
|
+
|
|
204
|
+
function createMockTargetDir(path: string) {
|
|
205
|
+
const dirHandle = {
|
|
206
|
+
name: path.split("/").pop() || "",
|
|
207
|
+
getDirectoryHandle: (jest.fn() as any).mockImplementation(
|
|
208
|
+
async (name: string) => {
|
|
209
|
+
const childPath = `${path}/${name}`;
|
|
210
|
+
if (!createdDirs.has(childPath)) {
|
|
211
|
+
createdDirs.set(childPath, createMockTargetDir(childPath));
|
|
212
|
+
}
|
|
213
|
+
return createdDirs.get(childPath);
|
|
214
|
+
},
|
|
215
|
+
),
|
|
216
|
+
getFileHandle: (jest.fn() as any).mockImplementation(
|
|
217
|
+
async (name: string) => {
|
|
218
|
+
const filePath = `${path}/${name}`;
|
|
219
|
+
if (!createdFiles.has(filePath)) {
|
|
220
|
+
createdFiles.set(filePath, { name, path: filePath });
|
|
221
|
+
}
|
|
222
|
+
return createdFiles.get(filePath);
|
|
223
|
+
},
|
|
224
|
+
),
|
|
225
|
+
};
|
|
226
|
+
return dirHandle;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
const mockTargetRoot = createMockTargetDir("shadowclaw-shadow-claw");
|
|
230
|
+
|
|
231
|
+
const mockOpfsRoot = {
|
|
232
|
+
getDirectoryHandle: (jest.fn() as any).mockImplementation(
|
|
233
|
+
async (name: string) => {
|
|
234
|
+
if (name === LEGACY_OPFS_ROOT) {
|
|
235
|
+
return mockLegacyRoot;
|
|
236
|
+
}
|
|
237
|
+
if (name === "shadowclaw-shadow-claw") {
|
|
238
|
+
return mockTargetRoot;
|
|
239
|
+
}
|
|
240
|
+
throw new DOMException("Not found", "NotFoundError");
|
|
241
|
+
},
|
|
242
|
+
),
|
|
243
|
+
};
|
|
244
|
+
|
|
245
|
+
Object.defineProperty(globalThis, "navigator", {
|
|
246
|
+
value: {
|
|
247
|
+
storage: {
|
|
248
|
+
getDirectory: (jest.fn() as any).mockResolvedValue(mockOpfsRoot),
|
|
249
|
+
},
|
|
250
|
+
},
|
|
251
|
+
configurable: true,
|
|
252
|
+
writable: true,
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
const mockDb = {} as ShadowClawDatabase;
|
|
256
|
+
await migrateLegacyOpfs(mockDb);
|
|
257
|
+
|
|
258
|
+
expect(mockWriteFileHandle).toHaveBeenCalledTimes(2);
|
|
259
|
+
expect(mockSetConfig).toHaveBeenCalledWith(
|
|
260
|
+
mockDb,
|
|
261
|
+
CONFIG_KEYS.OPFS_MIGRATED_FROM_LEGACY,
|
|
262
|
+
"true",
|
|
263
|
+
);
|
|
264
|
+
});
|
|
265
|
+
|
|
266
|
+
it("falls back to writeOpfsPathViaWorker on Safari/iPad when writeFileHandle throws unsupported", async () => {
|
|
267
|
+
const mockFile = new File(["test content"], "doc.txt", {
|
|
268
|
+
type: "text/plain",
|
|
269
|
+
});
|
|
270
|
+
|
|
271
|
+
const mockLegacyRoot = {
|
|
272
|
+
entries: async function* () {
|
|
273
|
+
yield [
|
|
274
|
+
"doc.txt",
|
|
275
|
+
{
|
|
276
|
+
kind: "file",
|
|
277
|
+
getFile: jest.fn(async () => mockFile),
|
|
278
|
+
},
|
|
279
|
+
];
|
|
280
|
+
},
|
|
281
|
+
};
|
|
282
|
+
|
|
283
|
+
const mockTargetFile = { name: "doc.txt" };
|
|
284
|
+
const mockTargetRoot = {
|
|
285
|
+
getDirectoryHandle: jest.fn(),
|
|
286
|
+
getFileHandle: (jest.fn() as any).mockResolvedValue(mockTargetFile),
|
|
287
|
+
};
|
|
288
|
+
|
|
289
|
+
const mockOpfsRoot = {
|
|
290
|
+
getDirectoryHandle: (jest.fn() as any).mockImplementation(
|
|
291
|
+
async (name: string) => {
|
|
292
|
+
if (name === LEGACY_OPFS_ROOT) return mockLegacyRoot;
|
|
293
|
+
if (name === "shadowclaw-shadow-claw") return mockTargetRoot;
|
|
294
|
+
throw new DOMException("Not found", "NotFoundError");
|
|
295
|
+
},
|
|
296
|
+
),
|
|
297
|
+
};
|
|
298
|
+
|
|
299
|
+
Object.defineProperty(globalThis, "navigator", {
|
|
300
|
+
value: {
|
|
301
|
+
storage: {
|
|
302
|
+
getDirectory: (jest.fn() as any).mockResolvedValue(mockOpfsRoot),
|
|
303
|
+
},
|
|
304
|
+
},
|
|
305
|
+
configurable: true,
|
|
306
|
+
writable: true,
|
|
307
|
+
});
|
|
308
|
+
|
|
309
|
+
mockWriteFileHandle.mockRejectedValueOnce(
|
|
310
|
+
new Error("Writable file streams are not supported"),
|
|
311
|
+
);
|
|
312
|
+
|
|
313
|
+
const mockDb = {} as ShadowClawDatabase;
|
|
314
|
+
await migrateLegacyOpfs(mockDb);
|
|
315
|
+
|
|
316
|
+
expect(mockWriteFileHandle).toHaveBeenCalledTimes(1);
|
|
317
|
+
expect(mockWriteOpfsPathViaWorker).toHaveBeenCalledWith(
|
|
318
|
+
["shadowclaw-shadow-claw", "doc.txt"],
|
|
319
|
+
mockFile,
|
|
320
|
+
);
|
|
321
|
+
expect(mockSetConfig).toHaveBeenCalledWith(
|
|
322
|
+
mockDb,
|
|
323
|
+
CONFIG_KEYS.OPFS_MIGRATED_FROM_LEGACY,
|
|
324
|
+
"true",
|
|
325
|
+
);
|
|
326
|
+
});
|
|
327
|
+
});
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { CONFIG_KEYS, LEGACY_OPFS_ROOT } from "../config/config.js";
|
|
2
|
+
import { getConfig } from "../db/getConfig.js";
|
|
3
|
+
import { setConfig } from "../db/setConfig.js";
|
|
4
|
+
import { getOpfsRootDirName } from "./storage.js";
|
|
5
|
+
import { writeFileHandle, writeOpfsPathViaWorker } from "./writeFileHandle.js";
|
|
6
|
+
import type { ShadowClawDatabase } from "../db/types.js";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Recursively copy entries from a source OPFS directory to a target OPFS directory.
|
|
10
|
+
*/
|
|
11
|
+
async function copyOpfsEntriesRecursively(
|
|
12
|
+
sourceDir: FileSystemDirectoryHandle,
|
|
13
|
+
targetDir: FileSystemDirectoryHandle,
|
|
14
|
+
pathSegments: string[],
|
|
15
|
+
): Promise<void> {
|
|
16
|
+
for await (const [name, handle] of (sourceDir as any).entries()) {
|
|
17
|
+
if (handle.kind === "directory") {
|
|
18
|
+
const nextTargetDir = await targetDir.getDirectoryHandle(name, {
|
|
19
|
+
create: true,
|
|
20
|
+
});
|
|
21
|
+
await copyOpfsEntriesRecursively(handle, nextTargetDir, [
|
|
22
|
+
...pathSegments,
|
|
23
|
+
name,
|
|
24
|
+
]);
|
|
25
|
+
} else if (handle.kind === "file") {
|
|
26
|
+
const file = await handle.getFile();
|
|
27
|
+
const targetFileHandle = await targetDir.getFileHandle(name, {
|
|
28
|
+
create: true,
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
try {
|
|
32
|
+
await writeFileHandle(targetFileHandle, file);
|
|
33
|
+
} catch (writeErr) {
|
|
34
|
+
const message =
|
|
35
|
+
writeErr instanceof Error ? writeErr.message : String(writeErr);
|
|
36
|
+
const needsOpfsWorkerFallback = message.includes(
|
|
37
|
+
"Writable file streams are not supported",
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
if (!needsOpfsWorkerFallback) {
|
|
41
|
+
throw writeErr;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
await writeOpfsPathViaWorker([...pathSegments, name], file);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Perform a one-time migration of OPFS workspace files and directories from the
|
|
52
|
+
* legacy unnamespaced root directory ("shadowclaw") to the active namespaced
|
|
53
|
+
* deployment root directory if not already done.
|
|
54
|
+
*/
|
|
55
|
+
export async function migrateLegacyOpfs(db: ShadowClawDatabase): Promise<void> {
|
|
56
|
+
if (!db) {
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
try {
|
|
61
|
+
const alreadyMigrated = await getConfig(
|
|
62
|
+
db,
|
|
63
|
+
CONFIG_KEYS.OPFS_MIGRATED_FROM_LEGACY,
|
|
64
|
+
);
|
|
65
|
+
if (alreadyMigrated === "true") {
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
} catch {
|
|
69
|
+
// ignore read error
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const targetRootName = getOpfsRootDirName();
|
|
73
|
+
if (targetRootName === LEGACY_OPFS_ROOT) {
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (
|
|
78
|
+
typeof navigator === "undefined" ||
|
|
79
|
+
!navigator.storage ||
|
|
80
|
+
typeof navigator.storage.getDirectory !== "function"
|
|
81
|
+
) {
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
try {
|
|
86
|
+
const opfsRoot = await navigator.storage.getDirectory();
|
|
87
|
+
let legacyRootHandle: FileSystemDirectoryHandle;
|
|
88
|
+
|
|
89
|
+
try {
|
|
90
|
+
legacyRootHandle = await opfsRoot.getDirectoryHandle(LEGACY_OPFS_ROOT);
|
|
91
|
+
} catch {
|
|
92
|
+
// Legacy OPFS folder does not exist (fresh installation or already cleaned up)
|
|
93
|
+
try {
|
|
94
|
+
await setConfig(db, CONFIG_KEYS.OPFS_MIGRATED_FROM_LEGACY, "true");
|
|
95
|
+
} catch {
|
|
96
|
+
// ignore write error
|
|
97
|
+
}
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const targetRootHandle = await opfsRoot.getDirectoryHandle(targetRootName, {
|
|
102
|
+
create: true,
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
await copyOpfsEntriesRecursively(legacyRootHandle, targetRootHandle, [
|
|
106
|
+
targetRootName,
|
|
107
|
+
]);
|
|
108
|
+
} catch (err) {
|
|
109
|
+
console.warn("Legacy OPFS migration warning:", err);
|
|
110
|
+
} finally {
|
|
111
|
+
try {
|
|
112
|
+
await setConfig(db, CONFIG_KEYS.OPFS_MIGRATED_FROM_LEGACY, "true");
|
|
113
|
+
} catch {
|
|
114
|
+
// ignore write error
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{n as e}from"./rolldown-runtime-aKtaBQYM.js";import{i as t}from"./app-routes-B0ePT49v.js";const n=new class{loading=!1;models=new Map;getModelInfo(e){return this.models.get(e.toLowerCase())??null}registerModelInfo(e,t){this.models.set(e.toLowerCase(),t)}clear(){this.models.clear()}async fetchModelInfo(e,t,n){if(e.modelsUrl){this.loading=!0;try{let r=new Headers;if(r.set(`Content-Type`,`application/json`),e.headers)for(let[t,n]of Object.entries(e.headers))r.set(t,n);if(n)for(let[e,t]of Object.entries(n))r.set(e,t);if(t&&e.apiKeyHeader){let n=e.apiKeyHeaderFormat;r.set(e.apiKeyHeader,n?n.replace(`{key}`,t):t)}let i=await fetch(e.modelsUrl,{headers:r});if(!i.ok)throw Error(`HTTP ${i.status} ${i.statusText}`);let a=await i.json(),o=Array.isArray(a.data)?a.data:Array.isArray(a.models)?a.models:[];for(let e of o){if(!e.id)continue;let t=e.context_length??e.context_window??0,n=e.max_completion_tokens||e.per_request_limits?.completion_tokens||e.top_provider?.max_completion_tokens||null,r=typeof e.supports_tools==`boolean`?e.supports_tools:typeof e.supportsTools==`boolean`?e.supportsTools:void 0,i=this.extractModalities(e,`input`),a=this.extractModalities(e,`output`),o=this.modalitiesInclude(i,`image`,`vision`),s=this.modalitiesInclude(i,`audio`,`voice`,`hearing`),c=this.modalitiesInclude(i,`video`),l=e.id===`openrouter/free`||this.supportedParametersInclude(e,`image`,`vision`,`audio`,`tool`,`structured`),u=this.extractReasoning(e);!t&&Array.isArray(e.providers)&&e.providers.length>0&&(t=e.providers[0]?.context_length||0),this.registerModelInfo(e.id,{contextWindow:t,maxOutput:n,...r!==void 0&&{supportsTools:r},...i.length>0&&{inputModalities:i},...a.length>0&&{outputModalities:a},...o!==void 0&&{supportsImageInput:o},...s!==void 0&&{supportsAudioInput:s},...c!==void 0&&{supportsVideoInput:c},...u&&{reasoning:u},...l&&{routesByRequestFeatures:l}})}o.length>0&&console.log(`[ModelRegistry] Registered ${o.length} models for provider "${e.id}"`)}catch(t){console.error(`[ModelRegistry] Error fetching models for ${e.id}:`,t)}finally{this.loading=!1}}}extractModalities(e,t){let n=t===`input`?e.input_modalities||e.inputModalities:e.output_modalities||e.outputModalities,r=e.architecture||{},i=t===`input`?r.input_modalities||r.inputModalities:r.output_modalities||r.outputModalities,a=typeof r.modality==`string`?r.modality:``,o=this.parseArchitectureModality(a,t),s=[...this.normalizeStringArray(n),...this.normalizeStringArray(i),...o];return Array.from(new Set(s))}extractReasoning(e){let t=e?.reasoning;if(!t||typeof t!=`object`)return;let n=this.normalizeStringArray(t.supported_efforts),r=typeof t.default_effort==`string`?t.default_effort.toLowerCase():void 0,i=typeof t.default_enabled==`boolean`?t.default_enabled:void 0,a=typeof t.supports_max_tokens==`boolean`?t.supports_max_tokens:void 0,o=typeof t.mandatory==`boolean`?t.mandatory:void 0;if(!(n.length===0&&r===void 0&&i===void 0&&a===void 0&&o===void 0))return{...n.length>0&&{supportedEfforts:n},...r!==void 0&&{defaultEffort:r},...i!==void 0&&{defaultEnabled:i},...a!==void 0&&{supportsMaxTokens:a},...o!==void 0&&{mandatory:o}}}modalitiesInclude(e,...t){if(e.length!==0)return t.some(t=>e.some(e=>e.includes(t)))}normalizeStringArray(e){return Array.isArray(e)?e.filter(e=>typeof e==`string`).map(e=>e.toLowerCase()):[]}parseArchitectureModality(e,t){if(!e)return[];let[n=``,r=``]=e.toLowerCase().split(`->`).map(e=>e.trim());return(t===`input`?n:r).split(/[+,/\s]+/).map(e=>e.trim()).filter(Boolean)}supportedParametersInclude(e,...t){let n=this.normalizeStringArray(e.supported_parameters||e.supportedParameters);return t.some(e=>n.some(t=>t.includes(e)))}};var r=e({ASSISTANT_NAME:()=>i,BASH_DEFAULT_TIMEOUT_SEC:()=>900,BASH_MAX_TIMEOUT_SEC:()=>f,BEDROCK_PROXY_MODELS_URL:()=>T,BEDROCK_PROXY_URL:()=>w,CONFIG_KEYS:()=>V,CONTEXT_WINDOW_SIZE:()=>50,DB_VERSION:()=>2,DEFAULT_DEV_HOST:()=>H,DEFAULT_DEV_IP:()=>DEFAULT_DEV_IP,DEFAULT_DEV_PORT:()=>U,DEFAULT_GROUP_ID:()=>v,DEFAULT_MAX_ITERATIONS:()=>50,DEFAULT_MAX_TOKENS:()=>o,DEFAULT_PROMPT_API_BACKEND:()=>DEFAULT_PROMPT_API_BACKEND,DEFAULT_PROMPT_API_DTYPE_STRATEGY:()=>DEFAULT_PROMPT_API_DTYPE_STRATEGY,DEFAULT_PROMPT_API_FALLBACK_MODEL:()=>G,DEFAULT_PROVIDER:()=>l,DEFAULT_SUBAGENT_MAX_PARALLEL:()=>5,DEFAULT_SUBAGENT_WORKSPACE_MODE:()=>W,DEFAULT_TASK_SERVER_ENABLED:()=>!1,DEFAULT_TASK_SERVER_URL:()=>K,DEFAULT_TRANSFORMERS_JS_BACKEND:()=>DEFAULT_TRANSFORMERS_JS_BACKEND,DEFAULT_TRANSFORMERS_JS_DTYPE_STRATEGY:()=>DEFAULT_TRANSFORMERS_JS_DTYPE_STRATEGY,DEFAULT_TRANSFORMERS_JS_MODEL:()=>DEFAULT_TRANSFORMERS_JS_MODEL,DEFAULT_VM_BOOT_HOST:()=>m,DEFAULT_VM_NETWORK_RELAY_URL:()=>p,FETCH_MAX_RESPONSE:()=>d,GENERAL_ACCOUNT_PROVIDER_CAPABILITIES:()=>M,IMESSAGE_POLL_TIMEOUT:()=>25,IMESSAGE_REQUEST_TIMEOUT_MS:()=>S,LEGACY_DB_NAME:()=>h,LEGACY_OPFS_ROOT:()=>LEGACY_OPFS_ROOT,LLAMAFILE_PROXY_MODELS_URL:()=>k,LLAMAFILE_PROXY_URL:()=>O,MODEL_OUTPUT_LIMITS:()=>s,OAUTH_PROVIDER_DEFINITIONS:()=>N,OLLAMA_PROXY_MODELS_URL:()=>j,OLLAMA_PROXY_URL:()=>A,OPFS_ROOT:()=>_,PEERJS_DEFAULT_HOST:()=>C,PEERJS_DEFAULT_PATH:()=>`/`,PEERJS_DEFAULT_PORT:()=>443,PEERJS_DEFAULT_SECURE:()=>!0,PROCESS_LOOP_INTERVAL:()=>100,PROVIDERS:()=>P,SCHEDULER_INTERVAL:()=>u,TELEGRAM_API_BASE:()=>y,TELEGRAM_MAX_LENGTH:()=>x,TELEGRAM_POLL_TIMEOUT:()=>30,TELEGRAM_PROXY_BASE:()=>b,TRANSFORMERS_JS_PROXY_MODELS_URL:()=>D,TRANSFORMERS_JS_PROXY_URL:()=>E,buildTriggerPattern:()=>a,getAvailableProviders:()=>L,getDbName:()=>g,getDefaultProvider:()=>I,getGeneralAccountProviderCapabilities:()=>z,getModelMaxTokens:()=>c,getProvider:()=>F,getProviderApiKeyConfigKey:()=>R,getProviderTokenAuthScheme:()=>B});const i=`ShadowClaw`;function a(e){let t=e.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`);return RegExp(`(^|\\s)@${t}\\b`,`i`)}a(i);const o=8192,s=[{pattern:`claude-fable-5`,maxTokens:128e3},{pattern:`claude-sonnet-5`,maxTokens:128e3},{pattern:`claude-opus-5`,maxTokens:128e3},{pattern:`claude-opus-4-8`,maxTokens:128e3},{pattern:`claude-opus-4`,maxTokens:128e3},{pattern:`claude-sonnet-4`,maxTokens:64e3},{pattern:`claude-haiku-4`,maxTokens:64e3},{pattern:`claude-3-5`,maxTokens:8192},{pattern:`claude-3`,maxTokens:4096},{pattern:`gpt-5`,maxTokens:128e3},{pattern:`gpt-4o`,maxTokens:16384},{pattern:`gpt-4.1`,maxTokens:32768},{pattern:`gpt-4-turbo`,maxTokens:4096},{pattern:`gpt-4`,maxTokens:8192},{pattern:`gpt-3.5`,maxTokens:4096},{pattern:`qwen-2.5`,maxTokens:32768},{pattern:`Qwen3.5`,maxTokens:32768},{pattern:`qwen3.5`,maxTokens:32768},{pattern:`Qwen3`,maxTokens:32768},{pattern:`qwen3`,maxTokens:32768},{pattern:`gemma-4`,maxTokens:16384},{pattern:`gemini-nano`,maxTokens:4096},{pattern:`phi-mini`,maxTokens:9216},{pattern:`aion`,maxTokens:9216},{pattern:`gemma-3-1b-it-ONNX-GQA`,maxTokens:32768},{pattern:`gemma-3-1b-it-ONNX`,maxTokens:32768},{pattern:`gemma-3`,maxTokens:32768},{pattern:`Qwen3-0.6B-ONNX`,maxTokens:32768},{pattern:`Qwen3.5`,maxTokens:32768},{pattern:`Llama-3.2`,maxTokens:32768},{pattern:`SmolLM`,maxTokens:8192},{pattern:`DeepSeek-R1`,maxTokens:32768},{pattern:`Phi-4`,maxTokens:16384},{pattern:`Phi-3.5`,maxTokens:16384},{pattern:`LFM2`,maxTokens:16384},{pattern:`gpt-oss`,maxTokens:32768},{pattern:`browser-built-in`,maxTokens:4096},{pattern:`mesh`,maxTokens:32768},{pattern:`openrouter/free`,maxTokens:32768},{pattern:`qwen3:8b`,maxTokens:4096},{pattern:`llama3:8b`,maxTokens:8192}];function c(e){if(!e)return o;let t=n.getModelInfo(e);if(t){if(typeof t.maxOutput==`number`){let e=t.contextWindow?Math.max(8192,Math.floor(t.contextWindow/2)):32768;return Math.min(t.maxOutput,e)}if(t.contextWindow){let e;return e=t.contextWindow>=2e5?131072:t.contextWindow>=1e5?65536:32768,Math.min(e,Math.floor(t.contextWindow/2))}}for(let{pattern:t,maxTokens:n}of s)if(e.includes(t))return n;return o}const l=`prompt_api`,u=6e4,d=102400,f=1800,p=`wss://relay.widgetry.org/`,m=`http://localhost:8888`,h=`shadowclaw`;function g(){let e=t();return e?`shadowclaw-${e}`:h}g();const _=`shadowclaw`,v=`br:main`,y=`https://api.telegram.org/bot`,b=`/telegram/bot`,x=4096,S=15e3,C=`0.peerjs.com`,w=`http://localhost:8888/bedrock-proxy/invoke`,T=`http://localhost:8888/bedrock-proxy/models`,E=`http://localhost:8888/transformers-js-proxy/chat/completions`,D=`http://localhost:8888/transformers-js-proxy/models`,O=`http://localhost:8888/llamafile-proxy/chat/completions`,k=`http://localhost:8888/llamafile-proxy/models`,A=`http://localhost:8888/ollama-proxy/chat/completions`,j=`http://localhost:8888/ollama-proxy/models`,M={github:{providerId:`github`,name:`GitHub`,aliases:[`github`,`api.github.com`],modes:[`oauth`,`token`],defaultMode:`oauth`,serviceTypes:[`http_api`,`git_remote`],authTypes:[`token`,`oauth`],tokenAuth:{token:{headerName:`Authorization`,headerPrefix:`token `},oauth:{headerName:`Authorization`,headerPrefix:`Bearer `}},oauth:{authorizeUrl:`https://github.com/login/oauth/authorize`,tokenUrl:`https://github.com/login/oauth/access_token`,defaultScopes:[`repo`,`read:user`],usePkce:!0,clientAuthMethod:`request_body`,scopeSeparator:`space`}},gitlab:{providerId:`gitlab`,name:`GitLab`,aliases:[`gitlab`,`gitlab.com`],modes:[`oauth`,`token`],defaultMode:`oauth`,serviceTypes:[`http_api`,`git_remote`],authTypes:[`token`,`oauth`],tokenAuth:{token:{headerName:`PRIVATE-TOKEN`,headerPrefix:``},oauth:{headerName:`Authorization`,headerPrefix:`Bearer `}},tokenAuthByServiceType:{git_remote:{token:{headerName:`Authorization`,headerPrefix:`Bearer `},oauth:{headerName:`Authorization`,headerPrefix:`Bearer `}}},oauth:{authorizeUrl:`https://gitlab.com/oauth/authorize`,tokenUrl:`https://gitlab.com/oauth/token`,defaultScopes:[`read_api`,`read_user`],usePkce:!0,clientAuthMethod:`request_body`,scopeSeparator:`space`}},figma:{providerId:`figma`,name:`Figma`,aliases:[`figma`,`api.figma.com`],modes:[`oauth`,`token`],defaultMode:`oauth`,serviceTypes:[`http_api`],authTypes:[`token`,`oauth`],tokenAuth:{token:{headerName:`X-Figma-Token`,headerPrefix:``},oauth:{headerName:`Authorization`,headerPrefix:`Bearer `}},oauth:{authorizeUrl:`https://www.figma.com/oauth`,tokenUrl:`https://api.figma.com/v1/oauth/token`,refreshUrl:`https://api.figma.com/v1/oauth/refresh`,defaultScopes:[],usePkce:!0,clientAuthMethod:`basic_header`,scopeSeparator:`space`}},notion:{providerId:`notion`,name:`Notion`,aliases:[`notion`,`api.notion.com`,`notion.so`],modes:[`oauth`,`token`],defaultMode:`oauth`,serviceTypes:[`http_api`],authTypes:[`token`,`oauth`],tokenAuth:{token:{headerName:`Authorization`,headerPrefix:`Bearer `},oauth:{headerName:`Authorization`,headerPrefix:`Bearer `}},oauth:{authorizeUrl:`https://api.notion.com/v1/oauth/authorize`,tokenUrl:`https://api.notion.com/v1/oauth/token`,defaultScopes:[],usePkce:!0,clientAuthMethod:`basic_header`,scopeSeparator:`space`}},microsoft_graph:{providerId:`microsoft_graph`,name:`Microsoft Graph`,aliases:[`microsoft`,`graph.microsoft.com`,`microsoft_graph`],modes:[`oauth`,`token`],defaultMode:`oauth`,serviceTypes:[`http_api`],authTypes:[`token`,`oauth`],tokenAuth:{token:{headerName:`Authorization`,headerPrefix:`Bearer `},oauth:{headerName:`Authorization`,headerPrefix:`Bearer `}},oauth:{authorizeUrl:`https://login.microsoftonline.com/common/oauth2/v2.0/authorize`,tokenUrl:`https://login.microsoftonline.com/common/oauth2/v2.0/token`,defaultScopes:[`openid`,`profile`,`offline_access`,`User.Read`],usePkce:!0,clientAuthMethod:`request_body`,scopeSeparator:`space`}},yahoo_mail:{providerId:`yahoo_mail`,name:`Yahoo Mail`,aliases:[`yahoo`,`yahoo_mail`,`mail.yahoo.com`],modes:[`oauth`,`token`],defaultMode:`oauth`,serviceTypes:[`http_api`],authTypes:[`token`,`oauth`],tokenAuth:{token:{headerName:`Authorization`,headerPrefix:`Bearer `},oauth:{headerName:`Authorization`,headerPrefix:`Bearer `}},oauth:{authorizeUrl:`https://api.login.yahoo.com/oauth2/request_auth`,tokenUrl:`https://api.login.yahoo.com/oauth2/get_token`,defaultScopes:[`mail-r`,`mail-w`],usePkce:!0,clientAuthMethod:`request_body`,scopeSeparator:`space`}},google:{providerId:`google`,name:`Google`,aliases:[`google`,`googleapis.com`],modes:[`oauth`,`token`],defaultMode:`oauth`,serviceTypes:[`http_api`],authTypes:[`token`,`oauth`],tokenAuth:{token:{headerName:`Authorization`,headerPrefix:`Bearer `},oauth:{headerName:`Authorization`,headerPrefix:`Bearer `}},oauth:{authorizeUrl:`https://accounts.google.com/o/oauth2/v2/auth`,tokenUrl:`https://oauth2.googleapis.com/token`,defaultScopes:[`openid`,`profile`,`email`],usePkce:!0,clientAuthMethod:`request_body`,scopeSeparator:`space`}},atlassian:{providerId:`atlassian`,name:`Atlassian`,aliases:[`atlassian`,`api.atlassian.com`],modes:[`oauth`,`token`,`basic`],defaultMode:`basic`,serviceTypes:[`http_api`,`git_remote`],authTypes:[`token`,`oauth`,`basic_userpass`],tokenAuth:{token:{headerName:`Authorization`,headerPrefix:`Bearer `},oauth:{headerName:`Authorization`,headerPrefix:`Bearer `},basic:{headerName:`Authorization`,headerPrefix:`Basic `}},oauth:{authorizeUrl:`https://auth.atlassian.com/authorize`,tokenUrl:`https://auth.atlassian.com/oauth/token`,defaultScopes:[],usePkce:!0,clientAuthMethod:`request_body`,scopeSeparator:`space`}},slack:{providerId:`slack`,name:`Slack`,aliases:[`slack`,`slack.com`],modes:[`oauth`,`token`],defaultMode:`oauth`,serviceTypes:[`http_api`],authTypes:[`token`,`oauth`],tokenAuth:{token:{headerName:`Authorization`,headerPrefix:`Bearer `},oauth:{headerName:`Authorization`,headerPrefix:`Bearer `}},oauth:{authorizeUrl:`https://slack.com/oauth/v2/authorize`,tokenUrl:`https://slack.com/api/oauth.v2.access`,defaultScopes:[],usePkce:!1,clientAuthMethod:`request_body`,scopeSeparator:`comma`}},linear:{providerId:`linear`,name:`Linear`,aliases:[`linear`,`api.linear.app`,`linear.app`],modes:[`oauth`,`token`],defaultMode:`oauth`,serviceTypes:[`http_api`],authTypes:[`token`,`oauth`],tokenAuth:{token:{headerName:`Authorization`,headerPrefix:`Bearer `},oauth:{headerName:`Authorization`,headerPrefix:`Bearer `}},oauth:{authorizeUrl:`https://linear.app/oauth/authorize`,tokenUrl:`https://api.linear.app/oauth/token`,defaultScopes:[],usePkce:!0,clientAuthMethod:`request_body`,scopeSeparator:`space`}},azure_devops:{providerId:`azure_devops`,name:`Azure DevOps`,aliases:[`azure_devops`,`dev.azure.com`],modes:[`oauth`,`token`],defaultMode:`oauth`,serviceTypes:[`http_api`,`git_remote`],authTypes:[`token`,`oauth`,`basic_userpass`,`ssh_key`],tokenAuth:{token:{headerName:`Authorization`,headerPrefix:`Bearer `},oauth:{headerName:`Authorization`,headerPrefix:`Bearer `}},tokenAuthByServiceType:{git_remote:{token:{headerName:`Authorization`,headerPrefix:`Basic `},oauth:{headerName:`Authorization`,headerPrefix:`Basic `}}},oauth:{authorizeUrl:`https://app.vssps.visualstudio.com/oauth2/authorize`,tokenUrl:`https://app.vssps.visualstudio.com/oauth2/token`,defaultScopes:[`vso.code`,`vso.profile`,`offline_access`],usePkce:!1,clientAuthMethod:`request_body`,scopeSeparator:`space`}},custom_mcp:{providerId:`custom_mcp`,name:`Custom MCP`,aliases:[`custom_mcp`],modes:[`oauth`,`token`],defaultMode:`oauth`,serviceTypes:[`mcp_remote`,`webmcp_local`],authTypes:[`none`,`token`,`oauth`,`custom_header`,`ssh_key`],tokenAuth:{token:{headerName:`Authorization`,headerPrefix:`Bearer `},oauth:{headerName:`Authorization`,headerPrefix:`Bearer `}},oauth:{authorizeUrl:`https://example.com/oauth/authorize`,tokenUrl:`https://example.com/oauth/token`,defaultScopes:[],usePkce:!0,clientAuthMethod:`request_body`,scopeSeparator:`space`}}},N=Object.fromEntries(Object.values(M).filter(e=>!!e.oauth).map(e=>{let t=e.oauth;return[e.providerId,{id:e.providerId,name:e.name,authorizeUrl:t.authorizeUrl,tokenUrl:t.tokenUrl,redirectUri:t.redirectUri,defaultScopes:t.defaultScopes,usePkce:t.usePkce,clientAuthMethod:t.clientAuthMethod,scopeSeparator:t.scopeSeparator}]}));Object.fromEntries(Object.values(M).map(e=>[e.providerId,{providerId:e.providerId,modes:e.modes,defaultMode:e.defaultMode}]));const P={openrouter:{id:`openrouter`,name:`OpenRouter`,baseUrl:`https://openrouter.ai/api/v1/chat/completions`,format:`openai`,apiKeyHeader:`Authorization`,apiKeyHeaderFormat:`Bearer {key}`,headers:{"HTTP-Referer":`https://xt-ml.github.io/shadow-claw/`,"X-OpenRouter-Title":`ShadowClaw`},defaultModel:`openrouter/free`,modelsUrl:`https://openrouter.ai/api/v1/models`,requiresApiKey:!0,supportsStreaming:!0,reasoningParam:`reasoning`},huggingface:{id:`huggingface`,name:`HuggingFace`,baseUrl:`https://router.huggingface.co/v1/chat/completions`,format:`openai`,apiKeyHeader:`Authorization`,apiKeyHeaderFormat:`Bearer {key}`,headers:{},defaultModel:`meta-llama/Llama-3.1-8B-Instruct`,modelsUrl:`https://router.huggingface.co/v1/models`,requiresApiKey:!0,supportsStreaming:!0},bedrock_proxy:{id:`bedrock_proxy`,name:`AWS Bedrock (Local Proxy)`,baseUrl:w,format:`anthropic`,apiKeyHeader:`Authorization`,headers:{},defaultModel:`anthropic.claude-sonnet-4-6-v1:0`,modelsUrl:T,requiresApiKey:!1,supportsStreaming:!0,reasoningParam:`thinking`},gemini_proxy:{id:`gemini_proxy`,name:`Gemini (Local Proxy)`,baseUrl:`http://localhost:8888/gemini-proxy/chat/completions`,format:`openai`,apiKeyHeader:`x-goog-api-key`,headers:{},defaultModel:`gemini-2.0-flash`,modelsUrl:`http://localhost:8888/gemini-proxy/models`,requiresApiKey:!0,supportsStreaming:!0,reasoningParam:`thinkingConfig`},vertex_ai:{id:`vertex_ai`,name:`Vertex AI (Local Proxy)`,baseUrl:`http://localhost:8888/vertex-ai-proxy/chat/completions`,format:`openai`,apiKeyHeader:`x-vertex-project`,headers:{},defaultModel:`gemini-2.5-flash`,modelsUrl:`http://localhost:8888/vertex-ai-proxy/models`,requiresApiKey:!0,supportsStreaming:!0,reasoningParam:`thinkingConfig`},"mesh-llm":{id:`mesh-llm`,name:`Mesh LLM (Local Proxy)`,baseUrl:`http://localhost:8888/mesh-llm-proxy/chat/completions`,format:`mesh-llm`,apiKeyHeader:`Authorization`,headers:{},defaultModel:`mesh`,modelsUrl:`http://localhost:8888/mesh-llm-proxy/models`,requiresApiKey:!1,supportsStreaming:!0},ollama:{id:`ollama`,name:`Ollama (Local Proxy)`,baseUrl:A,format:`openai`,apiKeyHeader:`Authorization`,headers:{},defaultModel:`qwen3:8b`,modelsUrl:j,requiresApiKey:!1,supportsStreaming:!0},llamafile:{id:`llamafile`,name:`Llamafile (Local Proxy)`,baseUrl:O,format:`openai`,apiKeyHeader:`Authorization`,headers:{},defaultModel:`Qwen3.5-9B-Q5_K_S`,modelsUrl:k,requiresApiKey:!1,supportsStreaming:!0},transformers_js_local:{id:`transformers_js_local`,name:`Transformers.js (Local Proxy)`,baseUrl:E,format:`openai`,apiKeyHeader:`Authorization`,headers:{},defaultModel:`onnx-community/Qwen3-0.6B-ONNX`,modelsUrl:D,models:[`onnx-community/DeepSeek-R1-Distill-Qwen-1.5B-ONNX`,`onnx-community/gemma-3-1b-it-ONNX-GQA`,`onnx-community/gemma-3-1b-it-ONNX`,`onnx-community/gemma-4-E2B-it-ONNX`,`onnx-community/gemma-4-E2B-it-qat-mobile-ONNX`,`onnx-community/gemma-4-E4B-it-ONNX`,`onnx-community/gemma-4-E4B-it-qat-mobile-ONNX`,`onnx-community/gemma-4-E9B-it-ONNX`,`onnx-community/gemma-4-12B-it-ONNX`,`onnx-community/gemma-4-12B-it-qat-mobile-ONNX`,`onnx-community/gemma-4-E27B-it-ONNX`,`onnx-community/gpt-oss-20b-ONNX`,`onnx-community/LFM2-1.2B-ONNX`,`onnx-community/Llama-3.2-1B-Instruct-ONNX`,`onnx-community/Llama-3.2-3B-Instruct-ONNX`,`onnx-community/Phi-3.5-mini-instruct-onnx-web`,`onnx-community/Phi-4-mini-instruct-ONNX`,`onnx-community/Qwen3-0.6B-ONNX`,`onnx-community/Qwen3.5-0.8B-ONNX-OPT`,`onnx-community/Qwen3.5-4B-ONNX-OPT`,`HuggingFaceTB/SmolLM3-3B-ONNX`,`LiquidAI/LFM2.5-1.2B-Thinking-ONNX`,`webgpu/Qwen3-4B-ONNX`],requiresApiKey:!1,supportsStreaming:!0},transformers_js_browser:{id:`transformers_js_browser`,name:`Transformers.js (Browser)`,baseUrl:`local://transformers-js`,format:`transformers_js`,apiKeyHeader:`Authorization`,headers:{},defaultModel:`onnx-community/Qwen3-0.6B-ONNX`,modelsUrl:`https://huggingface.co/api/models?author=onnx-community`,models:[`onnx-community/Qwen3-0.6B-ONNX`,`onnx-community/gemma-3-1b-it-ONNX`,`onnx-community/gemma-3-1b-it-ONNX-GQA`,`onnx-community/gemma-4-E2B-it-ONNX`,`onnx-community/gemma-4-E4B-it-ONNX`,`onnx-community/gemma-4-E9B-it-ONNX`,`onnx-community/gemma-4-E27B-it-ONNX`,`onnx-community/gemma-4-12B-it-ONNX`,`onnx-community/gemma-4-E2B-it-qat-mobile-ONNX`,`onnx-community/gemma-4-E4B-it-qat-mobile-ONNX`,`onnx-community/gemma-4-12B-it-qat-mobile-ONNX`,`onnx-community/Phi-3.5-mini-instruct-onnx-web`,`onnx-community/Phi-4-mini-instruct-ONNX`,`onnx-community/Llama-3.2-1B-Instruct-ONNX`,`onnx-community/Llama-3.2-3B-Instruct-ONNX`,`webgpu/Qwen3-4B-ONNX`,`onnx-community/DeepSeek-R1-Distill-Qwen-1.5B-ONNX`,`onnx-community/gpt-oss-20b-ONNX`,`onnx-community/LFM2-1.2B-ONNX`,`LiquidAI/LFM2.5-1.2B-Thinking-ONNX`,`HuggingFaceTB/SmolLM3-3B-ONNX`,`onnx-community/Qwen3.5-0.8B-ONNX-OPT`,`onnx-community/Qwen3.5-4B-ONNX-OPT`],requiresApiKey:!1,supportsStreaming:!1},litert_lm_browser:{id:`litert_lm_browser`,name:`LiteRT-LM (Browser)`,baseUrl:`local://litert-lm`,format:`transformers_js`,apiKeyHeader:`Authorization`,headers:{},defaultModel:`litert-community/gemma-4-E2B-it-litert-lm`,models:[`litert-community/gemma-4-E2B-it-litert-lm`,`litert-community/gemma-4-E4B-it-litert-lm`],requiresApiKey:!1,supportsStreaming:!1},prompt_api:{id:`prompt_api`,name:`Prompt API (Browser)`,baseUrl:`builtin://language-model`,format:`prompt_api`,apiKeyHeader:`Authorization`,headers:{},defaultModel:`browser-built-in`,models:[`browser-built-in`],requiresApiKey:!1,supportsStreaming:!1}};function F(e){return P[e]||null}function I(){return P[l]}function L(){return Object.keys(P)}function R(e){return`api_key:${e}`}function z(e){return M[e]||null}function B(e,t,n=`http_api`){let r=z(e);return r&&(r.tokenAuthByServiceType?.[n]?.[t]||r.tokenAuth[t])||null}const V={ACTIVE_TOOL_PROFILE:`active_tool_profile`,ACTIVITY_LOG_DISK_LOGGING_ENABLED:`activity_log_disk_logging_enabled`,ALLOWED_CUSTOM_ELEMENTS:`allowed_custom_elements`,ALLOWED_CUSTOM_ELEMENT_HOST_PATTERNS:`allowed_custom_element_host_patterns`,ALLOWED_IFRAME_HOST_PATTERNS:`allowed_iframe_host_patterns`,API_KEY:`api_key`,ASSISTANT_NAME:`assistant_name`,BEDROCK_AUTH_MODE:`bedrock_auth_mode`,BEDROCK_PROFILE_FALLBACK:`bedrock_profile_fallback`,BEDROCK_REGION_FALLBACK:`bedrock_region_fallback`,BUILTIN_AI_SUBAGENT_ROUTING:`builtin_ai_subagent_routing`,BUILTIN_AI_TOOLS_BACKEND:`builtin_ai_tools_backend`,CHANNEL_ENABLED_PREFIX:`channel_enabled:`,CHAT_INPUT_AREA_HEIGHT:`chat_input_area_height`,CHAT_SPLIT_VIEW_ENABLED:`chat_split_view_enabled`,CHAT_SPLIT_VIEW_HEIGHT:`chat_split_view_height`,COMPACTION_ENGINE_PREFERENCE:`compaction_engine_preference`,CONTEXT_COMPRESSION_ENABLED:`context_compression_enabled`,CONVERSATIONS_HEIGHT:`conversations_height`,CUSTOM_TOOLS:`custom_tools`,DB_MIGRATED_FROM_LEGACY:`db_migrated_from_legacy`,DECLARATIVE_TOOLS_ENABLED:`declarative_tools_enabled`,DEFAULT_PINNED_PAGE:`default_pinned_page`,DIRECT_TOOL_COMMAND_POLICY:`direct_tool_command_policy`,ENABLED_TOOLS:`enabled_tools`,GIT_ACCOUNTS:`git_accounts`,GIT_AUTHOR_EMAIL:`git_author_email`,GIT_AUTHOR_NAME:`git_author_name`,GIT_CORS_PROXY:`git_cors_proxy`,GIT_DEFAULT_ACCOUNT:`git_default_account`,GIT_PASSWORD:`git_password`,GIT_PROXY_URL:`git_proxy_url`,GIT_TOKEN:`git_token`,GIT_USERNAME:`git_username`,IMESSAGE_API_KEY:`imessage_api_key`,IMESSAGE_CHAT_IDS:`imessage_chat_ids`,IMESSAGE_SERVER_URL:`imessage_server_url`,INTEGRATION_CONNECTIONS:`integration_connections`,MARKDOWN_FRONTMATTER_CHAT:`markdown_frontmatter_chat`,MARKDOWN_FRONTMATTER_FILE_VIEWER:`markdown_frontmatter_file_viewer`,MARKDOWN_FRONTMATTER_PAGES:`markdown_frontmatter_pages`,MARKDOWN_FRONTMATTER_TASKS:`markdown_frontmatter_tasks`,LAST_ACTIVE_GROUP:`last_active_group`,LAST_ACTIVE_PAGE:`last_active_page`,LAST_SELECTED_PINNED_PAGE:`last_selected_pinned_page`,LLAMAFILE_HOST:`llamafile_host`,LLAMAFILE_MODE:`llamafile_mode`,LLAMAFILE_OFFLINE:`llamafile_offline`,LLAMAFILE_PORT:`llamafile_port`,MAIN_GROUP_INDEX_SUPPRESSED:`main_group_index_suppressed`,MAIN_GROUP_README_SUPPRESSED:`main_group_readme_suppressed`,MAX_ITERATIONS:`max_iterations`,MAX_TOKENS:`max_tokens`,MESH_LLM_HOST:`mesh_llm_host`,MODEL:`model`,OAUTH_PROVIDER_DEFINITIONS:`oauth_provider_definitions`,OVERRIDE_PRERENDER_SKELETON:`override_prerender_skeleton`,PAGES_AUTO_REFRESH_INTERVAL:`pages_auto_refresh_interval`,PAGES_LIST:`pages_list`,PASSPHRASE_SALT:`passphrase_salt`,PASSPHRASE_VERIFY:`passphrase_verify`,PROMPT_API_BACKEND:`prompt_api_backend`,PROMPT_API_DTYPE_STRATEGY:`prompt_api_dtype_strategy`,PROMPT_API_FALLBACK_MODEL:`prompt_api_fallback_model`,PROMPT_API_ONBOARDING_SEEN:`prompt_api_onboarding_seen`,PEERJS_MY_ALIAS:`peerjs_my_alias`,PEERJS_MY_PEER_ID:`peerjs_my_peer_id`,PEERJS_PEER_ALIASES:`peerjs_peer_aliases`,PEERJS_SERVER_HOST:`peerjs_server_host`,PEERJS_SERVER_PATH:`peerjs_server_path`,PEERJS_SERVER_PORT:`peerjs_server_port`,PEERJS_SERVER_SECURE:`peerjs_server_secure`,PEERJS_TRUSTED_PEER_IDS:`peerjs_trusted_peer_ids`,PROVIDER:`provider`,PROXY_URL:`proxy_url`,PUSH_PROXY_URL:`push_proxy_url`,RATE_LIMIT_AUTO_ADAPT:`rate_limit_auto_adapt`,RATE_LIMIT_CALLS_PER_MINUTE:`rate_limit_calls_per_minute`,REASONING_EFFORT:`reasoning_effort`,REMOTE_MCP_CONNECTIONS:`remote_mcp_connections`,SERVICE_ACCOUNTS:`service_accounts`,SERVICE_DEFAULT_ACCOUNT:`service_default_account`,SIDEBAR_CHAT_HIDDEN:`sidebar_chat_hidden`,SIDEBAR_DEFAULT_PAGE:`sidebar_default_page`,SIDEBAR_FILES_HIDDEN:`sidebar_files_hidden`,SIDEBAR_PAGES_HIDDEN:`sidebar_pages_hidden`,SIDEBAR_TASKS_HIDDEN:`sidebar_tasks_hidden`,SIDEBAR_WIDTH:`sidebar_width`,SITE_CONFIG_SEEDED:`site_config_seeded`,STATIC_MAIN_SITE_SEEDED:`static_main_site_seeded`,STORAGE_HANDLE:`storage_handle`,SUBSCRIBER_ID:`subscriber_id`,STREAMING_ENABLED:`streaming_enabled`,SUBAGENT_MAX_PARALLEL:`subagent_max_parallel`,SUBAGENT_WORKSPACE_MODE:`subagent_workspace_mode`,SUPPRESSED_PAGES_LIST:`suppressed_pages_list`,SYSTEM_PROMPT_OVERRIDE:`system_prompt_override`,TASK_SERVER_ENABLED:`task_server_enabled`,TASK_SERVER_URL:`task_server_url`,TASK_SYNC_OUTBOX:`task_sync_outbox`,TELEGRAM_BOT_TOKEN:`telegram_bot_token`,TELEGRAM_CHAT_IDS:`telegram_chat_ids`,TELEGRAM_USE_PROXY:`telegram_use_proxy`,TOOL_PROFILES:`tool_profiles`,TRANSFORMERS_JS_BACKEND:`transformers_js_backend`,TRANSFORMERS_JS_DTYPE_STRATEGY:`transformers_js_dtype_strategy`,TRIGGER_PATTERN:`trigger_pattern`,USE_PROXY:`use_proxy`,VAPID_SUBJECT:`vapid_subject`,VM_BASH_FULL_INTERNET_ACCESS:`vm_bash_full_internet_access`,VM_BASH_TIMEOUT_SEC:`vm_bash_timeout_sec`,VM_BOOT_HOST:`vm_boot_host`,VM_BOOT_MODE:`vm_boot_mode`,VM_NETWORK_RELAY_URL:`vm_network_relay_url`,WEBMCP_MODE:`webmcp_mode`,WEBMCP_TOOLS_ENABLED:`webmcp_tools_enabled`,WEB_SEARCH_PROXY_URL:`web_search_proxy_url`,WEB_SEARCH_URL:`web_search_url`,WEB_SEARCH_USE_PROXY:`web_search_use_proxy`,SEARCH_FILES_MAX_FILE_BYTES:`search_files_max_file_bytes`,SEARCH_FILES_MAX_FILES_VISITED:`search_files_max_files_visited`,SEARCH_FILES_SKIP_DIRS:`search_files_skip_dirs`},H=`localhost`,U=8888,W=`automatic`,G=`onnx-community/Qwen3-0.6B-ONNX`,K=`http://localhost:8888/schedule`;export{g as A,u as C,a as D,b as E,R as F,B as I,n as L,z as M,c as N,r as O,F as P,P as S,x as T,h as _,U as a,_ as b,G as c,K as d,m as f,S as g,M as h,H as i,I as j,L as k,l,d as m,f as n,v as o,p,V as r,o as s,i as t,W as u,O as v,y as w,C as x,N as y};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{I as e,M as t,h as n,r,y as i}from"./config-AL77QAx4.js";import{t as a}from"./getConfig-D89uJgo5.js";import{t as o}from"./setConfig-DFMYnYLE.js";import{t as s}from"./ulid-BY7rQVLN.js";import{n as c,r as l}from"./crypto-C8c5wMzN.js";function u(e){return!e||e.authMode===`token`||e.authMode===`pat`?`token`:e.authMode===`basic`?`basic`:e.authMode===`oauth`||e.oauthProviderId||e.oauthClientId||e.oauthClientSecret||e.refreshToken||e.accessTokenExpiresAt||e.tokenType||e.oauthReauthRequired?`oauth`:`token`}function d(e){return u(e)}function f(e,t){return d(e)!==`oauth`||e.oauthReauthRequired||!e.refreshToken||!e.oauthProviderId||!e.oauthClientId?!1:t.forceRefresh?!0:e.accessTokenExpiresAt?e.accessTokenExpiresAt<=Date.now()+6e4:!1}async function p(e,t,n){if(!n.refreshToken||!n.oauthProviderId||!n.oauthClientId)return n;let i=await c(n.refreshToken);if(!i)return n;let a=n.oauthClientSecret?await c(n.oauthClientSecret):void 0,s=async i=>{let a=t.findIndex(e=>e.id===n.id);a!==-1&&(t[a]=i,await o(e,r.SERVICE_ACCOUNTS,t))},u=async()=>{let e=(n.oauthRefreshFailureCount||0)+1,t=e>=3,r={...n,oauthRefreshFailureCount:e,oauthReauthRequired:t,oauthReauthRequiredAt:t?n.oauthReauthRequiredAt||Date.now():void 0};return await s(r),r};try{let e=await fetch(`/oauth/refresh`,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({providerId:n.oauthProviderId,clientId:n.oauthClientId,clientSecret:a,refreshToken:i,scope:n.scopes,tokenUrl:n.oauthCustomTokenUrl})});if(!e.ok)return u();let t=await e.json();if(!t.accessToken)return u();let r=await l(t.accessToken);if(!r)return u();let o=n.refreshToken;if(t.refreshToken){let e=await l(t.refreshToken);e&&(o=e)}let c={...n,token:r,refreshToken:o,accessTokenExpiresAt:t.expiresIn?Date.now()+t.expiresIn*1e3:n.accessTokenExpiresAt,tokenType:t.tokenType||n.tokenType,scopes:t.scope?t.scope.split(/[\s,]+/).map(e=>e.trim()).filter(Boolean):n.scopes,oauthRefreshFailureCount:0,oauthReauthRequired:!1,oauthReauthRequiredAt:void 0};return await s(c),c}catch{return u()}}function m(e,r){if(e.oauthProviderId){let n=t(e.oauthProviderId);if(n)return n}let i=[e.service,e.hostPattern,r].filter(e=>!!e).map(e=>e.toLowerCase());for(let e of Object.values(n))if([e.providerId,...e.aliases||[]].map(e=>e.toLowerCase()).some(e=>i.some(t=>t.includes(e))))return e;return null}function h(e,t){let n=d(e),r=m(e,t);if(r){let e;return e=n===`oauth`?r.tokenAuth.oauth:n===`basic`&&r.tokenAuth.basic?r.tokenAuth.basic:r.tokenAuth.token,{headerName:e.headerName,headerPrefix:e.headerPrefix||``}}return{headerName:`Authorization`,headerPrefix:n===`basic`?`Basic `:`Bearer `}}function g(e,t){let n=[],r=-1,i=t.toLowerCase();for(let t of e){if(!t.hostPattern)continue;let e=t.hostPattern.toLowerCase();i.includes(e)&&(e.length>r?(r=e.length,n.length=0,n.push(t)):e.length===r&&n.push(t))}return n}function _(e,t){return e.length?t&&e.find(e=>d(e)===t)||e[0]:void 0}async function v(e,t,n={}){let i=await a(e,r.SERVICE_ACCOUNTS),o=Array.isArray(i)?i:[];if(o.length===0)return;let s;if(n.accountId&&(s=o.find(e=>e.id===n.accountId)),!s&&t){let e=g(o,t);s=n.authMode?_(e,n.authMode):_(e,e[0]?m(e[0],t)?.defaultMode:void 0)}if(!s){let t=await a(e,r.SERVICE_DEFAULT_ACCOUNT);t&&(s=o.find(e=>e.id===t))}if(!s&&n.authMode&&(s=_(o,n.authMode)),s||=o[0],!s)return;if(f(s,n)&&(s=await p(e,o,s)),d(s)===`oauth`&&s.oauthReauthRequired)return{token:``,service:s.service,hostPattern:s.hostPattern,headerName:`Authorization`,headerValue:``,accountId:s.id,authMode:`oauth`,reauthRequired:!0};let l=``;s.token&&(l=await c(s.token)??``);let{headerName:u,headerPrefix:v}=h(s,t),y=l;d(s)===`basic`&&s.basicUsername&&(y=btoa(`${s.basicUsername}:${l}`));let b=v?`${v}${y}`:y;return{token:l,service:s.service,hostPattern:s.hostPattern,headerName:u,headerValue:b,accountId:s.id,authMode:d(s)}}function y(e){return u(e)}function b(e){switch(e){case`azure-devops`:return`azure_devops`;default:return e}}function x(e){if(!e)return`generic`;let t=e.toLowerCase();return t.includes(`github`)?`github`:t.includes(`dev.azure.com`)||t.includes(`visualstudio.com`)?`azure-devops`:t.includes(`gitlab`)?`gitlab`:`generic`}function S(t){if(t.reauthRequired)return{};let n=t.provider||x(t.hostPattern||``),r=b(n),i=t.authMode||`token`;if(t.token&&r===`azure_devops`&&e(r,i,`git_remote`)?.headerPrefix===`Basic `)return{Authorization:`Basic ${btoa(`:`+t.token)}`};switch(n){case`azure-devops`:if(t.username&&t.password)return{Authorization:`Basic ${btoa(t.username+`:`+t.password)}`};break;default:break}if(t.token){let n=e(r,i,`git_remote`);return n?.headerName?{[n.headerName]:`${n.headerPrefix||``}${t.token}`}:{Authorization:`Bearer ${t.token}`}}return{}}function C(e){try{let t=new URL(e),n=t.pathname.replace(/\/+$/,``);return n?t.hostname+n:t.hostname}catch{return}}function w(e,t){let n=t.toLowerCase(),r=[],i=-1;for(let t of e){if(!t.hostPattern)continue;let e=t.hostPattern.toLowerCase();n.includes(e)&&(e.length>i?(i=e.length,r.length=0,r.push(t)):e.length===i&&r.push(t))}return r}function T(e,t){if(!e.length)return;if(!t)return e[0];let n=e.find(e=>y(e)===t);if(n)return n;if(t===`token`){let t=e.find(e=>y(e)===`token`&&!e.authMode);if(t)return t}return e[0]}async function E(e){if(e)return await c(e)??void 0}function D(e,t){return y(e)!==`oauth`||e.oauthReauthRequired||!e.refreshToken||!e.oauthProviderId||!e.oauthClientId?!1:t.forceRefresh?!0:e.accessTokenExpiresAt?e.accessTokenExpiresAt<=Date.now()+6e4:!1}async function O(e,t,n){if(!n.refreshToken||!n.oauthProviderId||!n.oauthClientId)return n;let i=await E(n.refreshToken);if(!i)return n;let a=n.oauthClientSecret?await E(n.oauthClientSecret):void 0,s=async i=>{let a=t.findIndex(e=>e.id===n.id);a!==-1&&(t[a]=i,await o(e,r.GIT_ACCOUNTS,t))},c=async()=>{let e=(n.oauthRefreshFailureCount||0)+1,t=e>=3,r={...n,oauthRefreshFailureCount:e,oauthReauthRequired:t,oauthReauthRequiredAt:t?n.oauthReauthRequiredAt||Date.now():void 0};return await s(r),r};try{let e=await fetch(`/oauth/refresh`,{body:JSON.stringify({clientId:n.oauthClientId,clientSecret:a,providerId:n.oauthProviderId,refreshToken:i,scope:n.scopes}),headers:{"content-type":`application/json`},method:`POST`});if(!e.ok)return c();let t=await e.json();if(!t.accessToken)return c();let r=await l(t.accessToken);if(!r)return c();let o=n.refreshToken;if(t.refreshToken){let e=await l(t.refreshToken);e&&(o=e)}let u={...n,token:r,refreshToken:o,accessTokenExpiresAt:t.expiresIn?Date.now()+t.expiresIn*1e3:n.accessTokenExpiresAt,tokenType:t.tokenType||n.tokenType,scopes:t.scope?t.scope.split(/[\s,]+/).map(e=>e.trim()).filter(Boolean):n.scopes,oauthRefreshFailureCount:0,oauthReauthRequired:!1,oauthReauthRequiredAt:void 0};return await s(u),u}catch{return c()}}async function k(e,t,n={}){let i=await a(e,r.GIT_ACCOUNTS);return Array.isArray(i)&&i.length>0?ee(e,i,t,n):A(e)}async function ee(e,t,n,i={}){let o;if(i.accountId&&(o=t.find(e=>e.id===i.accountId)),!o&&n){let e=C(n);e&&(o=T(w(t,e),i.authMode))}if(!o){let i=await a(e,r.GIT_DEFAULT_ACCOUNT);if(i){let e=t.find(e=>e.id===i);if(e)if(!n)o=e;else{let t=C(n);if(t&&e.hostPattern){let n=t?.toLowerCase(),r=e.hostPattern.toLowerCase();n?.includes(r)&&(o=e)}}}}if(!o&&!n&&i.authMode&&(o=T(t,i.authMode)),!o&&!n&&(o=t[0]),!o)return{authMode:`token`,authorEmail:void 0,authorName:void 0,password:void 0,provider:`generic`,token:void 0,username:void 0};D(o,i)&&(o=await O(e,t,o));let s=o.provider||x(o.hostPattern||``);return y(o)===`oauth`&&o.oauthReauthRequired?{accountId:o.id,authMode:`oauth`,authorEmail:o.authorEmail||void 0,authorName:o.authorName||void 0,hostPattern:o.hostPattern||void 0,password:void 0,provider:s,reauthRequired:!0,token:void 0,username:o.username||void 0}:{accountId:o.id,authMode:y(o),authorEmail:o.authorEmail||void 0,authorName:o.authorName||void 0,hostPattern:o.hostPattern||void 0,password:await E(o.password),provider:s,token:await E(o.token),username:o.username||void 0}}async function A(e){let t=await a(e,r.GIT_TOKEN),n=await a(e,r.GIT_PASSWORD);return{authMode:`token`,authorEmail:await a(e,r.GIT_AUTHOR_EMAIL)||void 0,authorName:await a(e,r.GIT_AUTHOR_NAME)||void 0,password:n?await E(n):void 0,provider:`generic`,token:t?await E(t):void 0,username:await a(e,r.GIT_USERNAME)||void 0}}function j(e){if(typeof e!=`string`||!e.trim())return!1;try{let t=new URL(e);return t.protocol===`https:`||t.protocol===`http:`}catch{return!1}}function M(e,t){if(!e||typeof e!=`object`)return null;let n=e;if(!n.serviceType||!n.authType)return null;if(n.serviceType!==t)throw Error(`Credential ref serviceType must match connection serviceType`);return{serviceType:n.serviceType,authType:n.authType,providerId:n.providerId||void 0,accountId:n.accountId||void 0,gitAccountId:n.gitAccountId||void 0,headerName:n.headerName||void 0,encryptedValue:n.encryptedValue||void 0}}function N(e){if(!e||typeof e!=`object`)return null;let t=e;return!t.id||!t.label||!t.serviceType||!t.transport||typeof t.enabled!=`boolean`||typeof t.createdAt!=`number`||typeof t.updatedAt!=`number`||!j(t.serverUrl)||t.serviceType!==`mcp_remote`&&t.serviceType!==`webmcp_local`||t.transport!==`streamable_http`&&t.transport!==`sse`&&t.transport!==`websocket`?null:{id:t.id,label:t.label,serviceType:t.serviceType,serverUrl:t.serverUrl,transport:t.transport,enabled:t.enabled,autoReconnectOAuth:t.autoReconnectOAuth===!0,createdAt:t.createdAt,updatedAt:t.updatedAt,credentialRef:M(t.credentialRef,t.serviceType)}}async function P(e){let t=await a(e,r.REMOTE_MCP_CONNECTIONS);if(!Array.isArray(t))return[];let n=[];for(let e of t){let t=N(e);t&&n.push(t)}return n}async function F(e,t){await o(e,r.REMOTE_MCP_CONNECTIONS,t)}async function te(e){return P(e)}async function I(e,t){if(!t)return null;let n=await P(e);return n.find(e=>e.id===t)||n.find(e=>e.label.toLowerCase()===t.toLowerCase())||null}async function ne(e,t){if(!t?.label?.trim())throw Error(`Connection label is required`);if(!j(t.serverUrl))throw Error(`Connection serverUrl must be an absolute http(s) URL`);let n=t.serviceType||`mcp_remote`;if(n!==`mcp_remote`&&n!==`webmcp_local`)throw Error(`Unsupported serviceType for remote MCP connection`);let r=await P(e),i=Date.now();if(t.id){let a=r.findIndex(e=>e.id===t.id);if(a!==-1){let o=r[a],s={...o,label:t.label.trim(),serviceType:n,serverUrl:t.serverUrl,transport:t.transport,enabled:t.enabled??o.enabled,autoReconnectOAuth:t.autoReconnectOAuth??o.autoReconnectOAuth,updatedAt:i};return r[a]=s,await F(e,r),s}}let a={id:t.id||s(),label:t.label.trim(),serviceType:n,serverUrl:t.serverUrl,transport:t.transport,enabled:t.enabled??!0,autoReconnectOAuth:t.autoReconnectOAuth??!1,createdAt:i,updatedAt:i,credentialRef:null};return r.push(a),await F(e,r),a}async function re(e,t,n){if(!t)return null;let r=await P(e),i=r.findIndex(e=>e.id===t);if(i===-1)return null;let a=r[i],o=n?M(n,a.serviceType):null,s={...a,credentialRef:o,updatedAt:Date.now()};return r[i]=s,await F(e,r),s}async function L(e,t){if(!t)return!1;let n=await P(e),r=n.filter(e=>e.id!==t);return r.length===n.length?!1:(await F(e,r),!0)}function R(e){return e===`oauth`?`oauth`:`token`}async function z(e,t,n={}){let r=await I(e,t);if(!r)return null;let i=r.credentialRef;if(!i||i.authType===`none`)return{connection:r,authType:`none`,headers:{}};if(i.authType===`custom_header`){if(!i.headerName||!i.encryptedValue)return{connection:r,authType:`custom_header`,headers:{}};let e=await c(i.encryptedValue);return{connection:r,authType:`custom_header`,headers:e?{[i.headerName]:e}:{}}}let a=R(i.authType);if(i.accountId){let t=await v(e,r.serverUrl,{accountId:i.accountId,authMode:a,forceRefresh:n.forceRefresh});return t?t.reauthRequired?{connection:r,authType:i.authType,headers:{},reauthRequired:!0}:{connection:r,authType:i.authType,headers:t.headerValue?{[t.headerName]:t.headerValue}:{}}:{connection:r,authType:i.authType,headers:{}}}if(i.gitAccountId){let t=await k(e,r.serverUrl,{accountId:i.gitAccountId,authMode:a,forceRefresh:n.forceRefresh});return t.reauthRequired?{connection:r,authType:i.authType,headers:{},reauthRequired:!0}:{connection:r,authType:i.authType,headers:S(t)}}return{connection:r,authType:i.authType,headers:{}}}const B=new Map;function V(e){return typeof e==`object`&&!!e&&`method`in e&&`id`in e&&!(`result`in e)&&!(`error`in e)}function H(e){let t=(e.requestedSchema||{}).properties||{},n={};for(let[e,r]of Object.entries(t))`default`in r?n[e]=r.default:r.type===`boolean`&&(n[e]=!0);return n}var U=class extends Error{constructor(e){super(e),this.name=`InvalidRemoteMcpSessionError`}},W=class extends Error{status;constructor(e,t){super(t),this.name=`HttpRemoteMcpError`,this.status=e}},G=class extends Error{connectionId;constructor(e){super(`OAuth reconnect required for remote MCP connection`),this.name=`McpReauthRequiredError`,this.connectionId=e}};function K(e,t){return!e.headers||typeof e.headers.get!=`function`?null:e.headers.get(t)}function ie(e){return/no valid session id provided/i.test(e)}function q(e,t){let n=t&&`error`in t?t.error.message||`Remote MCP JSON-RPC error`:``;return ie(n)?new U(n):e.ok?Error(n||`Remote MCP JSON-RPC error`):new W(e.status,n?`Remote MCP HTTP error: ${e.status} (${n})`:`Remote MCP HTTP error: ${e.status}`)}function ae(e){if(!e)return null;let t=null,n=e.split(/\r?\n/);for(let e of n){let n=e.trim();if(!n.startsWith(`data:`))continue;let r=n.slice(5).trim();if(!(!r||r===`[DONE]`))try{let e=JSON.parse(r);e&&typeof e==`object`&&`jsonrpc`in e&&(t=e)}catch{}}return t}function oe(e){if(!e)return null;try{return JSON.parse(e)}catch{return null}}async function J(e,t,n){let r=await fetch(e,{method:`POST`,headers:{"content-type":`application/json`,accept:`application/json, text/event-stream`,...t},body:JSON.stringify(n)}),i=(K(r,`content-type`)||``).toLowerCase(),a=null;if(typeof r.text==`function`){let e=await r.text();a=i.includes(`text/event-stream`)?ae(e):oe(e)}else try{a=await r.json()}catch{a=null}return{response:r,payload:a}}async function se(e,t,n){let{response:r,payload:i}=await J(e,{...t,"mcp-session-id":n},{jsonrpc:`2.0`,method:`notifications/initialized`,params:{}});if(!r.ok||i&&`error`in i)throw q(r,i)}async function Y(e,t,n){let r=B.get(e);if(r?.sessionId)return r;let{response:i,payload:a}=await J(t,n,{jsonrpc:`2.0`,id:`initialize-${Date.now().toString(36)}`,method:`initialize`,params:{protocolVersion:`2025-03-26`,capabilities:{elicitation:{}},clientInfo:{name:`shadowclaw-remote-mcp-client`,version:`1.0.0`}}});if(!i.ok||a&&`error`in a)throw q(i,a);let o=K(i,`mcp-session-id`)||`local-${Date.now()}-${Math.random().toString(36).slice(2)}`,s={sessionId:o,protocolVersion:K(i,`mcp-protocol-version`)||a?.result?.protocolVersion,lastUsedAt:Date.now()};return await se(t,n,o),B.set(e,s),s}async function X(e,t,n,r,i){let a=await Y(e,t,n),o=async e=>{let a={jsonrpc:`2.0`,id:Date.now().toString(),method:r,params:i||{}},o={...n,"mcp-session-id":e},{response:s,payload:c}=await J(t,o,a),l=0;for(;V(c)&&l<5&&(l++,c.method===`elicitation/create`);){let e=H(c.params||{});({response:s,payload:c}=await J(t,o,{jsonrpc:`2.0`,id:c.id,result:{action:`accept`,content:e}}))}if(V(c))throw Error(`Unsupported server request: ${c.method}`);if(!s.ok||!c||`error`in c)throw q(s,c);return c.result};try{let t=await o(a.sessionId);return a.lastUsedAt=Date.now(),B.set(e,a),t}catch(r){if(!(r instanceof U))throw r;B.delete(e),a=await Y(e,t,n);let i=await o(a.sessionId);return a.lastUsedAt=Date.now(),B.set(e,a),i}}function Z(e){e&&B.delete(e)}async function Q(e,t,n,r){let i=await z(e,t);if(!i)throw Error(`Remote MCP connection not found`);if(i.reauthRequired)throw new G(t);let{connection:a,authType:o,headers:s}=i;if(a.transport!==`streamable_http`)throw Error(`Unsupported remote MCP transport`);try{return await X(t,a.serverUrl,s,n,r)}catch(i){if(!(i instanceof W)||i.status!==401||o!==`oauth`)throw i;Z(t);let a=await z(e,t,{forceRefresh:!0});if(!a||a.reauthRequired)throw new G(t);try{return await X(t,a.connection.serverUrl,a.headers,n,r)}catch(e){throw e instanceof W&&e.status===401?new G(t):e}}}async function ce(e,t){let n=await Q(e,t,`tools/list`);return Array.isArray(n.tools)?n.tools:[]}async function le(e,t,n,r={}){return Q(e,t,`tools/call`,{name:n,arguments:r})}async function ue(e,t){let n=[],r;try{r=await z(e,t)}catch(e){let t=e instanceof Error?e.message:String(e);return n.push({step:`Resolve authentication`,status:`error`,detail:t}),{success:!1,error:t,toolCount:0,toolNames:[],steps:n}}if(!r)return n.push({step:`Resolve authentication`,status:`error`,detail:`Connection not found`}),{success:!1,error:`Connection not found`,toolCount:0,toolNames:[],steps:n};if(r.reauthRequired){let e=`OAuth token expired or revoked — re-authenticate in Settings`;return n.push({step:`Resolve authentication`,status:`error`,detail:e}),{success:!1,error:e,toolCount:0,toolNames:[],steps:n}}n.push({step:`Resolve authentication`,status:`ok`,detail:`Auth type: ${r.authType}`});let{connection:i,authType:a,headers:o}=r;if(i.transport!==`streamable_http`){let e=`Unsupported transport: ${i.transport}`;return n.push({step:`Establish MCP session`,status:`error`,detail:e}),{success:!1,error:e,toolCount:0,toolNames:[],steps:n}}Z(t);try{await Y(t,i.serverUrl,o),n.push({step:`Establish MCP session`,status:`ok`,detail:`Session established`})}catch(r){let s=r instanceof Error?r.message:String(r);if(n.push({step:`Establish MCP session`,status:`error`,detail:s}),r instanceof W&&r.status===401&&a===`oauth`){Z(t);let r=await z(e,t,{forceRefresh:!0});if(r&&!r.reauthRequired){n.push({step:`Refresh OAuth token`,status:`ok`,detail:`Token refreshed, retrying`}),i=r.connection,o=r.headers;try{await Y(t,i.serverUrl,o),n.push({step:`Establish MCP session`,status:`ok`,detail:`Session established`})}catch(e){let t=e instanceof Error?e.message:String(e),r=e instanceof W&&e.status===401?`${t} — re-authorize in Settings → Accounts`:t;return n.push({step:`Establish MCP session`,status:`error`,detail:r}),{success:!1,error:r,toolCount:0,toolNames:[],steps:n}}}else return n.push({step:`Refresh OAuth token`,status:`error`,detail:`Token refresh failed — re-authenticate in Settings`}),{success:!1,error:s,toolCount:0,toolNames:[],steps:n}}else return{success:!1,error:s,toolCount:0,toolNames:[],steps:n}}try{let e=await X(t,i.serverUrl,o,`tools/list`),r=Array.isArray(e.tools)?e.tools:[],a=r.map(e=>e.name);return n.push({step:`Discover tools`,status:`ok`,detail:`${r.length} tool${r.length===1?``:`s`} available`}),{success:!0,error:null,toolCount:r.length,toolNames:a,steps:n}}catch(e){let t=e instanceof Error?e.message:String(e);return n.push({step:`Discover tools`,status:`error`,detail:t}),{success:!1,error:t,toolCount:0,toolNames:[],steps:n}}}function $(e,t,n,r){return{accessTokenExpiresAt:e.expiresIn?Date.now()+e.expiresIn*1e3:t.accessTokenExpiresAt,oauthReauthRequired:!1,oauthReauthRequiredAt:void 0,oauthRefreshFailureCount:0,refreshToken:r,scopes:e.scope?e.scope.split(/[\s,]+/).map(e=>e.trim()).filter(Boolean):t.scopes,token:n,tokenType:e.tokenType||t.tokenType}}async function de(e,t,n,i,a,s,u){if(!t.refreshToken)return{success:!1,error:`No refresh token available.`};let d=await c(t.refreshToken);if(!d)return{success:!1,error:`Failed to decrypt refresh token.`};let f=t.oauthClientSecret?await c(t.oauthClientSecret):void 0;try{let c=await fetch(`/oauth/refresh`,{body:JSON.stringify({clientId:t.oauthClientId,clientSecret:f||void 0,providerId:t.oauthProviderId,refreshToken:d,scope:t.scopes,tokenUrl:t.oauthCustomTokenUrl}),headers:{"content-type":`application/json`},method:`POST`});if(!c.ok)return{success:!1,error:`Token refresh request failed.`};let p=await c.json();if(!p.accessToken)return{success:!1,error:`No access token in refresh response.`};let m=await l(p.accessToken);if(!m)return{success:!1,error:`Failed to encrypt access token.`};let h=t.refreshToken;if(p.refreshToken){let e=await l(p.refreshToken);e&&(h=e)}let g=$({accessToken:p.accessToken,expiresIn:p.expiresIn,refreshToken:p.refreshToken,scope:p.scope,tokenType:p.tokenType},t,m,h);if(n===`service`&&s.accountId){let t=i.findIndex(e=>e.id===s.accountId);t!==-1&&(Object.assign(i[t],g),await o(e,r.SERVICE_ACCOUNTS,i))}else if(n===`git`&&s.gitAccountId){let t=a.findIndex(e=>e.id===s.gitAccountId);t!==-1&&(Object.assign(a[t],g),await o(e,r.GIT_ACCOUNTS,a))}return Z(u),{success:!0}}catch(e){return{success:!1,error:`Silent refresh failed: ${e instanceof Error?e.message:String(e)}`}}}async function fe(e,t,n={}){let s=await I(e,t);if(!s?.credentialRef)return{success:!1,error:`Connection not found.`};let u=s.credentialRef;if(u.authType!==`oauth`)return{success:!1,error:`This connection does not use OAuth authentication.`};let d=await a(e,r.SERVICE_ACCOUNTS),f=Array.isArray(d)?d:[],p=await a(e,r.GIT_ACCOUNTS),m=Array.isArray(p)?p:[],h,g=null;if(u.accountId?(h=f.find(e=>e.id===u.accountId),g=`service`):u.gitAccountId&&(h=m.find(e=>e.id===u.gitAccountId),g=`git`),!h||!g)return{error:`Linked account not found. Edit the connection to re-configure authentication.`,success:!1};let _=h.oauthClientId,v=h.oauthProviderId;if(!v||!_)return{error:`Account is missing OAuth provider or client ID. Edit the account in Settings → Accounts to fix.`,success:!1};if(h.refreshToken){let n=await de(e,h,g,f,m,u,t);if(n.success)return n}if(n.silentOnly)return{error:`Silent token refresh failed. Use Settings → Remote MCP → Reconnect OAuth for full re-authorization.`,success:!1};let y=h.oauthClientSecret?await c(h.oauthClientSecret):void 0,b=h.scopes,x=i[v],S=v===`custom_mcp`,C=S&&h.oauthCustomRedirectUri?h.oauthCustomRedirectUri:x?.redirectUri?x.redirectUri:`${globalThis.location?.origin||``}/oauth/callback`;try{let n=await fetch(`/oauth/authorize`,{body:JSON.stringify({providerId:v,clientId:_,clientSecret:y||void 0,redirectUri:C,scope:b,...S&&h.oauthCustomAuthorizeUrl?{authorizeUrl:h.oauthCustomAuthorizeUrl}:{},...S&&h.oauthCustomTokenUrl?{tokenUrl:h.oauthCustomTokenUrl}:{},...S&&typeof h.oauthCustomUsePkce==`boolean`?{usePkce:h.oauthCustomUsePkce}:{}}),headers:{"content-type":`application/json`},method:`POST`}),i=await n.json();if(!n.ok||!i.state||!i.authorizeUrl)throw Error(i.error||`OAuth authorize failed`);let a=window.open(i.authorizeUrl,`shadowclaw-oauth`,`popup=yes,width=540,height=720`);if(!a||a.closed||a.closed===void 0)throw Error(`OAuth popup was blocked by the browser. Please enable popups for this site and try again.`);let s=i.state,c=`pending`;for(let e=0;e<60;e++){let e=await fetch(`/oauth/session/${encodeURIComponent(s)}`),t=await e.json();if(!e.ok)throw Error(t.error||`OAuth session not found`);if(c=t.status||`pending`,c===`authorized`)break;if(c===`error`)throw Error(t.error||`OAuth authorization failed`);await new Promise(e=>setTimeout(e,1e3))}if(c!==`authorized`)throw Error(`OAuth authorization timed out`);let d=await fetch(`/oauth/token`,{body:JSON.stringify({state:s}),headers:{"content-type":`application/json`},method:`POST`}),p=await d.json();if(!d.ok||!p.accessToken)throw Error(p.error||`OAuth token exchange failed`);let x=await l(p.accessToken);if(!x)throw Error(`Failed to encrypt access token`);let w=h.refreshToken;if(p.refreshToken){let e=await l(p.refreshToken);e&&(w=e)}let T=$({accessToken:p.accessToken,expiresIn:p.expiresIn,refreshToken:p.refreshToken,scope:p.scope,tokenType:p.tokenType},h,x,w);if(g===`service`&&u.accountId){let t=f.findIndex(e=>e.id===u.accountId);t!==-1&&(Object.assign(f[t],T),await o(e,r.SERVICE_ACCOUNTS,f))}else if(g===`git`&&u.gitAccountId){let t=m.findIndex(e=>e.id===u.gitAccountId);t!==-1&&(Object.assign(m[t],T),await o(e,r.GIT_ACCOUNTS,m))}return Z(t),{success:!0}}catch(e){return{success:!1,error:e instanceof Error?e.message:String(e)}}}export{ue as a,I as c,S as d,x as f,u as h,ce as i,te as l,v as m,G as n,re as o,k as p,le as r,L as s,fe as t,ne as u};
|