@numa-tech/numa 1.24.0 → 1.26.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 +4 -0
- package/dist/business-issuer.js +5 -5
- package/dist/business-issuer.js.map +1 -1
- package/dist/cli.js +3 -0
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +1 -1
- package/dist/config.js +2 -2
- package/dist/config.js.map +1 -1
- package/dist/kb/catalog.js +33 -2
- package/dist/kb/catalog.js.map +1 -1
- package/dist/kb/chat-stream.d.ts +5 -0
- package/dist/kb/chat-stream.js +61 -0
- package/dist/kb/chat-stream.js.map +1 -0
- package/dist/kb/client.d.ts +75 -6
- package/dist/kb/client.js +114 -12
- package/dist/kb/client.js.map +1 -1
- package/dist/kb/commands.js +93 -8
- package/dist/kb/commands.js.map +1 -1
- package/dist/kb/config.d.ts +15 -3
- package/dist/kb/config.js +40 -21
- package/dist/kb/config.js.map +1 -1
- package/dist/kb/management-commands.d.ts +7 -0
- package/dist/kb/management-commands.js +86 -0
- package/dist/kb/management-commands.js.map +1 -0
- package/dist/kb/management-schemas.d.ts +106 -0
- package/dist/kb/management-schemas.js +33 -0
- package/dist/kb/management-schemas.js.map +1 -0
- package/dist/kb/transfers.d.ts +4 -0
- package/dist/kb/transfers.js +11 -4
- package/dist/kb/transfers.js.map +1 -1
- package/dist/kb/upload-decisions.d.ts +28 -0
- package/dist/kb/upload-decisions.js +23 -0
- package/dist/kb/upload-decisions.js.map +1 -0
- package/dist/kb/upload-state.d.ts +1 -0
- package/dist/kb/upload-state.js +1 -0
- package/dist/kb/upload-state.js.map +1 -1
- package/dist/kb/web-login.d.ts +10 -0
- package/dist/kb/web-login.js +25 -0
- package/dist/kb/web-login.js.map +1 -0
- package/dist/kb/web-page.d.ts +3 -0
- package/dist/kb/web-page.js +114 -0
- package/dist/kb/web-page.js.map +1 -0
- package/dist/kb/web-queue.d.ts +61 -0
- package/dist/kb/web-queue.js +101 -0
- package/dist/kb/web-queue.js.map +1 -0
- package/dist/kb/web.d.ts +26 -0
- package/dist/kb/web.js +234 -0
- package/dist/kb/web.js.map +1 -0
- package/dist/local-web/context-menu.d.ts +2 -0
- package/dist/local-web/context-menu.js +53 -0
- package/dist/local-web/context-menu.js.map +1 -0
- package/dist/local-web/file-workspace-style.d.ts +2 -0
- package/dist/local-web/file-workspace-style.js +58 -0
- package/dist/local-web/file-workspace-style.js.map +1 -0
- package/dist/local-web/file-workspace.d.ts +2 -0
- package/dist/local-web/file-workspace.js +39 -0
- package/dist/local-web/file-workspace.js.map +1 -0
- package/dist/local-web/security.d.ts +6 -0
- package/dist/local-web/security.js +51 -0
- package/dist/local-web/security.js.map +1 -0
- package/dist/login-recovery.js +8 -3
- package/dist/login-recovery.js.map +1 -1
- package/dist/mcp-gateway/profile.d.ts +4 -0
- package/dist/mcp-gateway/profile.js +6 -3
- package/dist/mcp-gateway/profile.js.map +1 -1
- package/dist/mcp-gateway/runtime.js +14 -0
- package/dist/mcp-gateway/runtime.js.map +1 -1
- package/dist/oss/transfer-queue.d.ts +7 -51
- package/dist/oss/transfer-queue.js +15 -308
- package/dist/oss/transfer-queue.js.map +1 -1
- package/dist/oss/web-page.js +21 -103
- package/dist/oss/web-page.js.map +1 -1
- package/dist/oss/web.js +4 -45
- package/dist/oss/web.js.map +1 -1
- package/dist/platform-profile.d.ts +25 -1
- package/dist/platform-profile.js +44 -1
- package/dist/platform-profile.js.map +1 -1
- package/dist/transfers/persistent-queue.d.ts +65 -0
- package/dist/transfers/persistent-queue.js +312 -0
- package/dist/transfers/persistent-queue.js.map +1 -0
- package/docs/design/kb-capability-upgrade.md +36 -0
- package/docs/design/kb-cli.md +4 -4
- package/docs/design/kb-web-workspace.md +97 -0
- package/docs/kb-access.md +86 -7
- package/examples/jev/README.md +65 -0
- package/examples/jev/platform-client.test.ts +136 -0
- package/examples/jev/platform-client.ts +122 -0
- package/package.json +9 -7
- package/scripts/export-kb-contract.py +25 -6
- package/skills/numa-jev/LICENSE +21 -0
- package/skills/numa-jev/SKILL.md +54 -0
- package/skills/numa-jev/assets/decision.json +37 -0
- package/skills/numa-jev/numa-skill.json +8 -0
- package/skills/numa-jev/references/application-integration.md +36 -0
- package/skills/numa-jev/references/mcp-usage.md +53 -0
- package/skills/numa-jev/references/upstream.md +13 -0
- package/src/kb/openapi-contract.json +2297 -566
package/dist/kb/web.js
ADDED
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
import { createServer } from 'node:http';
|
|
2
|
+
import { createHash, randomBytes } from 'node:crypto';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
import open from 'open';
|
|
5
|
+
import { appConfigDirectory } from '../app-config.js';
|
|
6
|
+
import { localWebHeaders, strictLocalJson, requireLocalOrigin, requireLocalAuthorization } from '../local-web/security.js';
|
|
7
|
+
import { createLocalPicker } from '../oss/local-picker.js';
|
|
8
|
+
import { OssError } from '../oss/errors.js';
|
|
9
|
+
import { KbError, sanitizeKbOutput } from './errors.js';
|
|
10
|
+
import { KbWebQueue } from './web-queue.js';
|
|
11
|
+
import { needsKbLogin } from './web-login.js';
|
|
12
|
+
import { KB_WEB_HTML, KB_WEB_CSS, KB_WEB_JS } from './web-page.js';
|
|
13
|
+
const fail = (status = 400) => new KbError('Invalid request.', 'kb_input_invalid', status);
|
|
14
|
+
export async function startKbWeb(options) {
|
|
15
|
+
if (options.port !== undefined && (!Number.isInteger(options.port) || options.port < 0 || options.port > 65535))
|
|
16
|
+
throw fail();
|
|
17
|
+
const picker = options.picker ?? createLocalPicker();
|
|
18
|
+
const defaultEnvironment = options.defaultEnvironment ?? '';
|
|
19
|
+
const environments = options.environments ?? [{ id: defaultEnvironment, name: '当前默认配置', endpoint: options.client.baseUrl, client: async () => options.client }];
|
|
20
|
+
if (new Set(environments.map(e => e.id)).size !== environments.length || !environments.some(e => e.id === defaultEnvironment))
|
|
21
|
+
throw fail();
|
|
22
|
+
async function createContext(environment) {
|
|
23
|
+
const root = await environment.client(), subject = (await root.identity()).id;
|
|
24
|
+
const namespace = createHash('sha256').update(JSON.stringify(environment.id ? [environment.id, root.binding, subject] : [root.binding, subject])).digest('hex');
|
|
25
|
+
const directory = join(options.directory ?? appConfigDirectory(), 'kb-transfers', namespace);
|
|
26
|
+
async function tenants() { if ((await root.identity()).id !== subject)
|
|
27
|
+
throw new KbError('Identity changed; restart kb web.', 'kb_identity_changed', 409); return root.listTenants(); }
|
|
28
|
+
async function client(tenant) { if (!(await tenants()).items.some(x => x.tenant_id === tenant))
|
|
29
|
+
throw new KbError('Tenant forbidden.', 'kb_auth_failed', 403); return root.forTenant(tenant); }
|
|
30
|
+
const queue = new KbWebQueue({ directory, client });
|
|
31
|
+
await queue.initialize();
|
|
32
|
+
return { tenants, client, queue };
|
|
33
|
+
}
|
|
34
|
+
const contexts = new Map();
|
|
35
|
+
function context(id) {
|
|
36
|
+
const environment = environments.find(e => e.id === id);
|
|
37
|
+
if (!environment)
|
|
38
|
+
throw fail();
|
|
39
|
+
let pending = contexts.get(id);
|
|
40
|
+
if (!pending) {
|
|
41
|
+
pending = createContext(environment);
|
|
42
|
+
contexts.set(id, pending);
|
|
43
|
+
void pending.catch(() => { if (contexts.get(id) === pending)
|
|
44
|
+
contexts.delete(id); });
|
|
45
|
+
}
|
|
46
|
+
return pending;
|
|
47
|
+
}
|
|
48
|
+
async function closeQueues() { const results = await Promise.allSettled([...contexts.values()].map(async (c) => (await c).queue.close())); const failed = results.find(r => r.status === 'rejected'); if (failed?.status === 'rejected')
|
|
49
|
+
throw failed.reason; }
|
|
50
|
+
try {
|
|
51
|
+
await context(defaultEnvironment);
|
|
52
|
+
}
|
|
53
|
+
catch (error) {
|
|
54
|
+
if (!needsKbLogin(error) || !environments.find(e => e.id === defaultEnvironment)?.login)
|
|
55
|
+
throw error;
|
|
56
|
+
}
|
|
57
|
+
const preparations = new AbortController();
|
|
58
|
+
const token = randomBytes(32).toString('base64url');
|
|
59
|
+
let origin = '', closed = false;
|
|
60
|
+
const logins = new Map();
|
|
61
|
+
let activeLogin;
|
|
62
|
+
function beginLogin(id) {
|
|
63
|
+
const environment = environments.find(e => e.id === id);
|
|
64
|
+
if (!environment?.login)
|
|
65
|
+
throw new KbError('Browser login unavailable.', 'kb_interactive_login_disabled', 400);
|
|
66
|
+
if (logins.get(id)?.status === 'pending')
|
|
67
|
+
return logins.get(id);
|
|
68
|
+
if (activeLogin)
|
|
69
|
+
throw new KbError('Another environment is logging in.', 'kb_login_busy', 409);
|
|
70
|
+
const state = { status: 'pending' };
|
|
71
|
+
logins.set(id, state);
|
|
72
|
+
const returnUrl = origin + '/#' + new URLSearchParams({ token, environment: id, login: 'return' });
|
|
73
|
+
activeLogin = (async () => {
|
|
74
|
+
try {
|
|
75
|
+
await environment.login(returnUrl, preparations.signal);
|
|
76
|
+
if (closed)
|
|
77
|
+
return;
|
|
78
|
+
// Existing queues retain their original subject; a different account must restart the workspace.
|
|
79
|
+
const contextAfterLogin = await context(id);
|
|
80
|
+
await contextAfterLogin.tenants();
|
|
81
|
+
state.status = 'succeeded';
|
|
82
|
+
}
|
|
83
|
+
catch (error) {
|
|
84
|
+
state.status = 'failed';
|
|
85
|
+
state.code = error instanceof KbError && ['kb_identity_changed', 'kb_auth_failed'].includes(error.code) ? error.code : 'kb_login_failed';
|
|
86
|
+
}
|
|
87
|
+
finally {
|
|
88
|
+
activeLogin = undefined;
|
|
89
|
+
}
|
|
90
|
+
})();
|
|
91
|
+
return state;
|
|
92
|
+
}
|
|
93
|
+
let resolved;
|
|
94
|
+
const done = new Promise(r => { resolved = r; });
|
|
95
|
+
function json(res, status, data) { localWebHeaders(res, 'application/json; charset=utf-8'); res.writeHead(status); res.end(JSON.stringify(data)); }
|
|
96
|
+
const field = (body, name) => { if (typeof body[name] !== 'string' || !body[name] || String(body[name]).length > 500)
|
|
97
|
+
throw fail(); return body[name]; };
|
|
98
|
+
const server = createServer((req, res) => {
|
|
99
|
+
void (async () => {
|
|
100
|
+
const url = new URL(req.url ?? '/', origin);
|
|
101
|
+
requireLocalOrigin(req, origin, url.pathname === '/');
|
|
102
|
+
const assets = { '/': ['text/html; charset=utf-8', KB_WEB_HTML], '/app.css': ['text/css; charset=utf-8', KB_WEB_CSS], '/app.js': ['text/javascript; charset=utf-8', KB_WEB_JS] };
|
|
103
|
+
if (req.method === 'GET' && Object.hasOwn(assets, url.pathname)) {
|
|
104
|
+
const [type, body] = assets[url.pathname];
|
|
105
|
+
localWebHeaders(res, type);
|
|
106
|
+
res.end(body);
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
requireLocalAuthorization(req, origin, token);
|
|
110
|
+
if (closed)
|
|
111
|
+
throw new KbError('Closing.', 'kb_web_closing', 503);
|
|
112
|
+
if (req.method === 'GET' && url.pathname === '/api/environments') {
|
|
113
|
+
json(res, 200, { ok: true, data: { defaultEnvironment, autoLogin: options.openBrowser !== false, items: environments.map(({ id, name, namespace, endpoint, login }) => ({ id, name, namespace, endpoint, loginAvailable: Boolean(login) })) } });
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
if (url.pathname === '/api/login') {
|
|
117
|
+
const id = url.searchParams.get('environment') ?? defaultEnvironment;
|
|
118
|
+
if (!environments.some(e => e.id === id))
|
|
119
|
+
throw fail();
|
|
120
|
+
if (req.method === 'POST') {
|
|
121
|
+
await strictLocalJson(req, []);
|
|
122
|
+
json(res, 200, { ok: true, data: beginLogin(id) });
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
if (req.method === 'GET') {
|
|
126
|
+
json(res, 200, { ok: true, data: logins.get(id) ?? { status: 'idle' } });
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
throw fail(405);
|
|
130
|
+
}
|
|
131
|
+
if (req.method === 'POST' && url.pathname === '/api/shutdown') {
|
|
132
|
+
const body = await strictLocalJson(req, ['confirmation']);
|
|
133
|
+
if (body.confirmation !== 'STOP_SERVICE')
|
|
134
|
+
throw fail();
|
|
135
|
+
res.once('finish', () => { void close().catch(() => { process.stderr.write('任务记录保存失败,请检查本地任务目录。\n'); }); });
|
|
136
|
+
json(res, 200, { ok: true, data: { stopped: true } });
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
const { tenants, client, queue } = await context(url.searchParams.get('environment') ?? defaultEnvironment);
|
|
140
|
+
let value;
|
|
141
|
+
if (req.method === 'GET' && url.pathname === '/api/tenants')
|
|
142
|
+
value = await tenants();
|
|
143
|
+
else if (req.method === 'GET' && url.pathname === '/api/collections')
|
|
144
|
+
value = await (await client(url.searchParams.get('tenant') ?? '')).listCollections();
|
|
145
|
+
else if (req.method === 'GET' && url.pathname === '/api/documents')
|
|
146
|
+
value = await (await client(url.searchParams.get('tenant') ?? '')).listDocuments(url.searchParams.get('collection') ?? '', Number(url.searchParams.get('offset') ?? 0), url.searchParams.get('q') ?? '');
|
|
147
|
+
else if (req.method === 'GET' && url.pathname === '/api/transfers') {
|
|
148
|
+
await tenants();
|
|
149
|
+
value = queue.list();
|
|
150
|
+
}
|
|
151
|
+
else if (req.method === 'GET' && url.pathname.startsWith('/api/ingestion/'))
|
|
152
|
+
value = await queue.ingestion(url.pathname.slice('/api/ingestion/'.length));
|
|
153
|
+
else if (req.method === 'POST' && url.pathname === '/api/upload') {
|
|
154
|
+
const body = await strictLocalJson(req, ['tenant', 'collection', 'folder']);
|
|
155
|
+
const tenant = field(body, 'tenant'), collection = field(body, 'collection');
|
|
156
|
+
if (typeof body.folder !== 'boolean')
|
|
157
|
+
throw fail();
|
|
158
|
+
const c = await client(tenant), collections = await c.listCollections();
|
|
159
|
+
if (!collections.collections.some(x => x.collection_id === collection && x.can_upload === true))
|
|
160
|
+
throw new KbError('Upload forbidden.', 'kb_auth_failed', 403);
|
|
161
|
+
const selected = body.folder ? await picker.pickFolder('upload') : await picker.pickFiles();
|
|
162
|
+
value = selected ? await queue.uploads(tenant, collection, Array.isArray(selected) ? selected : [selected], preparations.signal) : [];
|
|
163
|
+
}
|
|
164
|
+
else if (req.method === 'POST' && url.pathname === '/api/download') {
|
|
165
|
+
const body = await strictLocalJson(req, ['tenant', 'collection', 'document']);
|
|
166
|
+
const tenant = field(body, 'tenant'), collection = field(body, 'collection'), document = field(body, 'document');
|
|
167
|
+
await (await client(tenant)).downloadTicket(document);
|
|
168
|
+
const folder = await picker.pickFolder('download');
|
|
169
|
+
value = folder ? await queue.download(tenant, collection, document, folder) : [];
|
|
170
|
+
}
|
|
171
|
+
else if (req.method === 'POST' && url.pathname === '/api/delete') {
|
|
172
|
+
const body = await strictLocalJson(req, ['tenant', 'document', 'confirmation']);
|
|
173
|
+
if (body.confirmation !== 'DELETE_DOCUMENT')
|
|
174
|
+
throw fail();
|
|
175
|
+
await (await client(field(body, 'tenant'))).deleteDocument(field(body, 'document'));
|
|
176
|
+
value = { deleted: true };
|
|
177
|
+
}
|
|
178
|
+
else if (req.method === 'POST' && /^\/api\/transfers\/[^/]+\/(pause|resume|cancel)$/.test(url.pathname)) {
|
|
179
|
+
await tenants();
|
|
180
|
+
await strictLocalJson(req, []);
|
|
181
|
+
const [, , , id, action] = url.pathname.split('/');
|
|
182
|
+
await queue.action(id, action);
|
|
183
|
+
value = { ok: true };
|
|
184
|
+
}
|
|
185
|
+
else
|
|
186
|
+
throw fail(404);
|
|
187
|
+
// No tokens or signed tickets are returned by any local business endpoint.
|
|
188
|
+
json(res, 200, { ok: true, data: sanitizeKbOutput(value) });
|
|
189
|
+
})().catch(error => {
|
|
190
|
+
if (res.destroyed)
|
|
191
|
+
return;
|
|
192
|
+
if (res.headersSent) {
|
|
193
|
+
res.destroy();
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
const known = error instanceof KbError || error instanceof OssError;
|
|
197
|
+
const status = needsKbLogin(error) ? 401 : known && error.status && error.status >= 400 ? error.status : 502;
|
|
198
|
+
const code = known && /^(kb|oss)_[a-z_]+$/.test(error.code) ? error.code : 'kb_web_error';
|
|
199
|
+
if (code === 'oss_web_origin') {
|
|
200
|
+
json(res, status, { ok: false, error: { code, message: '请求来源校验未通过,请从 CLI 提供的本地工作台地址重新打开。' } });
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
const messages = { kb_auth_unavailable: '暂时无法获取登录凭据,请检查身份源连接或配置;未自动重新登录。', kb_invalid_response: 'KB 接口返回格式与客户端不兼容,请更新客户端或报告此错误。', kb_network_error: '无法连接 KB 服务或请求超时,请稍后重试。', kb_auth_required: '当前环境尚未登录或登录已过期,请登录当前环境。', kb_login_busy: '另一个环境正在登录,请完成后再试。', kb_login_failed: '登录未完成,请重试登录。', kb_write_result_unknown: '服务端写入结果尚未确认,请先刷新核对,避免重复提交。', kb_identity_changed: '登录身份已改变,请重新启动工作台。' };
|
|
204
|
+
json(res, status, { ok: false, error: { code, message: messages[code] ?? (status === 401 ? '登录已失效,请在 CLI 重新登录后再试。' : status === 403 ? '当前身份没有此操作权限。' : status === 409 ? '状态已变化,请刷新后重试。' : '操作未完成,请根据错误码核对接口或任务状态。') } });
|
|
205
|
+
});
|
|
206
|
+
});
|
|
207
|
+
let closing;
|
|
208
|
+
function close() { return closing ??= (async () => { closed = true; preparations.abort(); picker.close?.(); try {
|
|
209
|
+
await activeLogin;
|
|
210
|
+
await closeQueues();
|
|
211
|
+
}
|
|
212
|
+
finally {
|
|
213
|
+
server.closeAllConnections();
|
|
214
|
+
await new Promise(resolve => server.close(() => resolve()));
|
|
215
|
+
resolved();
|
|
216
|
+
} })(); }
|
|
217
|
+
try {
|
|
218
|
+
await new Promise((resolve, reject) => { server.once('error', reject); server.listen(options.port ?? 0, '127.0.0.1', () => { server.off('error', reject); resolve(); }); });
|
|
219
|
+
}
|
|
220
|
+
catch (e) {
|
|
221
|
+
await closeQueues();
|
|
222
|
+
throw e;
|
|
223
|
+
}
|
|
224
|
+
const address = server.address();
|
|
225
|
+
if (!address || typeof address === 'string') {
|
|
226
|
+
await close();
|
|
227
|
+
throw fail();
|
|
228
|
+
}
|
|
229
|
+
origin = `http://127.0.0.1:${address.port}`;
|
|
230
|
+
const url = `${origin}/#token=${token}`;
|
|
231
|
+
const browserOpened = options.openBrowser !== false && await (options.browserOpen ?? open)(url).then(() => true, () => false);
|
|
232
|
+
return { url, browserOpened, close, waitUntilClosed: () => done };
|
|
233
|
+
}
|
|
234
|
+
//# sourceMappingURL=web.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"web.js","sourceRoot":"","sources":["../../src/kb/web.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/** Embedded in both local workspaces; actions remain owned by their business adapters. */
|
|
2
|
+
export const LOCAL_CONTEXT_MENU_JS = String.raw `
|
|
3
|
+
function createLocalContextMenu(menu, onClose = () => {}) {
|
|
4
|
+
let owner = null;
|
|
5
|
+
function close(restore = false) {
|
|
6
|
+
onClose(); menu.hidden = true;
|
|
7
|
+
if (restore) owner?.focus();
|
|
8
|
+
}
|
|
9
|
+
function begin(event, anchor, parent = document.body) {
|
|
10
|
+
event.preventDefault(); close();
|
|
11
|
+
owner = anchor || event.currentTarget;
|
|
12
|
+
parent.append(menu); menu.replaceChildren();
|
|
13
|
+
}
|
|
14
|
+
function item(label, action, options = {}) {
|
|
15
|
+
const button = document.createElement('button');
|
|
16
|
+
button.textContent = label;
|
|
17
|
+
button.setAttribute('role', 'menuitem');
|
|
18
|
+
button.setAttribute('aria-disabled', String(Boolean(options.disabled)));
|
|
19
|
+
if (options.danger) button.className = 'danger';
|
|
20
|
+
button.onclick = () => {
|
|
21
|
+
if (options.disabled) { options.onDisabled?.(button); return; }
|
|
22
|
+
close(); action();
|
|
23
|
+
};
|
|
24
|
+
menu.append(button); return button;
|
|
25
|
+
}
|
|
26
|
+
function show(event, anchor) {
|
|
27
|
+
menu.hidden = false;
|
|
28
|
+
const bounds = anchor?.getBoundingClientRect();
|
|
29
|
+
menu.style.left = Math.max(8, Math.min(bounds ? bounds.left : event.clientX, window.innerWidth - menu.offsetWidth - 8)) + 'px';
|
|
30
|
+
menu.style.top = Math.max(8, Math.min(bounds ? bounds.bottom : event.clientY, window.innerHeight - menu.offsetHeight - 8)) + 'px';
|
|
31
|
+
[...menu.children].find(button => !button.disabled)?.focus();
|
|
32
|
+
}
|
|
33
|
+
document.addEventListener('click', event => { if (!menu.contains(event.target)) close(); });
|
|
34
|
+
document.addEventListener('keydown', event => {
|
|
35
|
+
if (menu.hidden) return;
|
|
36
|
+
if (event.key === 'Escape' || event.key === 'Tab') {
|
|
37
|
+
if (event.key === 'Escape') event.preventDefault();
|
|
38
|
+
close(true); return;
|
|
39
|
+
}
|
|
40
|
+
if (['ArrowDown', 'ArrowUp', 'Home', 'End'].includes(event.key)) {
|
|
41
|
+
event.preventDefault();
|
|
42
|
+
const buttons = [...menu.children].filter(button => !button.disabled);
|
|
43
|
+
const index = buttons.indexOf(document.activeElement);
|
|
44
|
+
const next = event.key === 'Home' ? 0 : event.key === 'End' ? buttons.length - 1
|
|
45
|
+
: (index + (event.key === 'ArrowDown' ? 1 : buttons.length - 1)) % buttons.length;
|
|
46
|
+
buttons[next]?.focus();
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
document.addEventListener('scroll', () => close(), true);
|
|
50
|
+
return { begin, item, show, close };
|
|
51
|
+
}
|
|
52
|
+
`;
|
|
53
|
+
//# sourceMappingURL=context-menu.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context-menu.js","sourceRoot":"","sources":["../../src/local-web/context-menu.ts"],"names":[],"mappings":"AAAA,0FAA0F;AAC1F,MAAM,CAAC,MAAM,qBAAqB,GAAG,MAAM,CAAC,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAkD9C,CAAC"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/** Shared local file workspace styling; OSS-specific controls are optional slots. */
|
|
2
|
+
export const FILE_WORKSPACE_CSS = String.raw `
|
|
3
|
+
.file-menu{position:fixed;z-index:20;min-width:175px;padding:5px;background:white;border:1px solid #d4ded6;border-radius:8px;box-shadow:0 8px 28px #20372e26}.file-menu button{display:block;width:100%;border:0;text-align:left;padding:9px 12px}.file-menu button:focus{background:#eff5f1}.file-menu button[aria-disabled=true]{color:#99a49e}.permission-tip{position:fixed;z-index:30;max-width:min(330px,calc(100vw - 16px));padding:10px 12px;background:#263c31;color:#fff;border-radius:6px;box-shadow:0 6px 24px #20372e26;font-size:12px;line-height:1.7;overflow-wrap:anywhere}
|
|
4
|
+
#statistics-result{display:grid;grid-template-columns:100px 1fr;gap:12px;margin:20px 0;font-variant-numeric:tabular-nums}#statistics-result dd{margin:0;font-weight:600}#statistics-status{margin-top:10px}
|
|
5
|
+
#statistics-dialog{width:min(640px,90vw);max-width:90vw;max-height:90vh;overflow:auto}#statistics-result dd{overflow-wrap:anywhere}.statistics-table{margin:22px 0 10px}.statistics-table caption{text-align:left;font-weight:600;margin-bottom:6px}.statistics-table th:first-child,.statistics-table td:first-child{width:44%;overflow-wrap:anywhere}.statistics-table th:not(:first-child),.statistics-table td:not(:first-child){text-align:right;font-variant-numeric:tabular-nums}.statistics-table td{color:#4a6554}#statistics-dialog .dialog-actions{position:sticky;bottom:-26px;background:#fff;padding:14px 0;margin-top:10px}
|
|
6
|
+
#links-dialog{width:min(680px,90vw);max-width:90vw;max-height:90vh;overflow:auto}#links-expires{margin-left:12px;max-width:100%}.links-renew{margin-top:12px;white-space:normal}#links-session-hint{margin:8px 0 12px}#links-result article{border-top:1px solid #dbe3de;padding:14px 0}#links-result h3{font-size:13px;overflow-wrap:anywhere;margin:0 0 8px}#links-result textarea{width:100%;font:11px/1.6 ui-monospace,monospace;resize:vertical;overflow-wrap:anywhere;min-height:72px}#links-result .link-copy{display:flex;align-items:center;gap:8px}#links-status{overflow-wrap:anywhere}#links-dialog .dialog-actions{position:sticky;bottom:-26px;background:white;padding:14px 0}
|
|
7
|
+
#operation-dialog{max-height:90vh;overflow:auto;width:min(520px,90vw)}
|
|
8
|
+
#destination-picker{margin-top:16px}#destination-hint{font-size:12px;margin-bottom:8px}.destination-tree{max-height:260px;overflow:auto;border:1px solid #dbe3de;border-radius:6px;padding:6px;background:#fafcfb}.destination-children{padding-left:18px}.destination-line{display:flex;align-items:center;gap:4px;min-height:34px;border-radius:4px}.destination-line button{border:0;background:transparent;padding:6px;color:#344b41}.destination-toggle{width:28px;flex-shrink:0}.destination-name{display:flex;align-items:center;gap:8px;flex:1;min-width:0;text-align:left;white-space:normal;overflow-wrap:anywhere}.destination-name .folder-icon{flex-shrink:0}.destination-item[aria-selected=true]>.destination-line{background:#dfede3}.destination-item:focus{outline:none}.destination-item:focus-visible>.destination-line{outline:2px solid #16805a;outline-offset:-2px}.destination-status{font-size:11px;color:#7b8d81;margin-left:32px}.destination-more{font-size:12px;margin:4px 0 4px 32px}.destination-editor{display:flex;flex-wrap:wrap;gap:6px;margin:6px 0 6px 32px}.destination-editor input{width:100%;min-width:0;padding:7px;border:1px solid #cbd9cf;border-radius:4px;background:white;color:#23322e}.destination-editor button{font-size:12px;padding:6px 9px}
|
|
9
|
+
#operation-dialog label{display:block;font-size:12px;margin:16px 0 8px}#operation-value{width:100%;border:1px solid #cbd9cf;padding:10px;border-radius:5px;color:#23322e}#operation-source{overflow-wrap:anywhere}#operation-help{margin-top:10px}#operation-error{color:#a7473d}
|
|
10
|
+
.operations-panel{flex-shrink:0;background:#f0f6f2;border-top:1px solid #cbd9cf;max-height:24vh;overflow:auto;padding:10px 26px;font-size:12px}.operations-panel>p{font-size:11px;color:#74867b;margin-top:5px}.operation-row{display:flex;align-items:center;gap:12px;padding:5px 0}.operation-row span{flex:1;overflow-wrap:anywhere}.operation-row button{font-size:12px;padding:5px 10px}.upload-actions{flex-wrap:wrap;justify-content:flex-end}
|
|
11
|
+
|
|
12
|
+
.icon-button{display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;min-width:34px;min-height:34px}
|
|
13
|
+
:root{font-family:Inter,-apple-system,BlinkMacSystemFont,"Segoe UI","PingFang SC",sans-serif;color:#23322e;background:#f5f7f5;font-size:14px;font-synthesis:none}*{box-sizing:border-box}body{margin:0}button,input,select{font:inherit}button,select{cursor:pointer}button{border:1px solid #d8e0db;background:white;color:#344b41;border-radius:6px;padding:8px 12px;white-space:nowrap}button:hover:not(:disabled){background:#eff5f1;border-color:#a5bcae}button:disabled{opacity:.4;cursor:not-allowed}input:focus-visible,button:focus-visible,select:focus-visible{outline:2px solid #16805a;outline-offset:2px}input[type=checkbox]{accent-color:#197854;width:15px;height:15px;cursor:pointer}input[type=search]{border:1px solid #dbe3de;border-radius:6px;padding:9px 12px;min-width:160px;background:#fafcfb;color:#23322e}select{border:0;background:transparent;color:#263d31;max-width:100%;padding:6px 24px 6px 0;font-weight:550}h1,h2,p{margin:0}h1{font-size:27px;letter-spacing:-.7px;font-weight:600}h2{font-size:15px;font-weight:600}.topbar{height:62px;padding:0 26px;background:#20372e;color:#ecf4ed;display:flex;align-items:center;gap:20px}.brand{font-size:24px;letter-spacing:-1px;font-weight:650;color:inherit;text-decoration:none}.brand span{font-size:16px;font-weight:400;letter-spacing:.5px;color:#a9c0b0;margin-left:12px}.local{font-size:11px;color:#cee0d5;display:flex;align-items:center;gap:6px}.local i{height:6px;width:6px;background:#8edaac;border-radius:50%}.topnote{margin-left:auto;color:#aac0b2;font-size:12px;letter-spacing:2px}.authorization{display:flex;align-items:center;justify-content:space-between;gap:24px;background:#fff;border-bottom:1px solid #dbe3de;padding:16px 26px}.grant-field{min-width:0;display:flex;align-items:center;gap:12px;flex:1}.grant-field label{font-size:12px;color:#7a8c80;white-space:nowrap}.session-controls{display:flex;align-items:center;gap:18px;flex-shrink:0}.expiry{display:flex;align-items:center;gap:10px;font-size:11px;color:#718076}.expiry strong{font-family:ui-monospace,SFMono-Regular,monospace;color:#2b674c;font-size:20px;font-weight:500;min-width:62px}.expiry strong.warning{color:#b45309}.expiry strong.expired{color:#bf403d}.check{display:flex;align-items:center;gap:5px;font-size:12px;white-space:nowrap}.quiet{background:transparent;border-color:transparent;color:#718577;padding:6px 8px}.primary{color:white;background:#227b54;border-color:#227b54}.primary:hover:not(:disabled){background:#196140;color:white}.danger{color:#9f4b40}.destructive{color:white;background:#a7473d;border-color:#a7473d}.notice{margin:0;padding:10px 26px;background:#fff4df;border-bottom:1px solid #ead9b8;color:#845422;font-size:13px;line-height:1.6}.notice.success{background:#e9f6ec;color:#266342;border-color:#c9e3d0}.workspace{display:grid;grid-template-columns:205px minmax(420px,1fr) 310px;min-height:calc(100vh - 137px)}.sidebar{border-right:1px solid #dbe3de;padding:30px 16px;display:flex;flex-direction:column;background:#f0f4f0;min-width:0}.eyebrow{font-size:10px;letter-spacing:1.7px;color:#89988d;font-weight:600}.sidebar .eyebrow{padding-left:10px}.root-button{display:flex;align-items:center;gap:10px;margin-top:18px;white-space:normal;text-align:left;overflow-wrap:anywhere;background:#e1ebe2;border:0;color:#24573d;font-size:13px}.folder-icon{display:inline-block;width:16px;height:11px;background:#9fbba1;border-radius:2px;position:relative;flex-shrink:0;margin-top:3px}.folder-icon:before{content:"";position:absolute;left:0;top:-3px;width:7px;height:4px;border-radius:2px 2px 0 0;background:inherit}.scope-label{font-size:11px;color:#86978a;margin:23px 10px 9px}.scope{font-family:ui-monospace,SFMono-Regular,monospace;font-size:12px;color:#637c6a;overflow-wrap:anywhere;line-height:1.7}.sidebar>.scope{padding:0 10px}.sidebar-bottom{margin-top:auto;padding:40px 10px 0;color:#607e68;font-size:12px}.sidebar-bottom p{margin-top:12px;line-height:1.8;color:#8b9b8e;font-size:11px}.files{background:white;min-width:0;padding:30px 28px 0;display:flex;flex-direction:column}.page-heading{display:flex;align-items:center;justify-content:space-between;margin-bottom:24px}.page-heading .eyebrow{margin-bottom:8px}.location{display:flex;align-items:center;gap:6px;border-top:1px solid #e8ede9;border-bottom:1px solid #e8ede9;padding:9px 0;min-width:0}.location nav{display:flex;align-items:center;flex-wrap:wrap;flex:1;gap:2px;min-width:0}.location nav button{padding:4px 7px;border:0;font-size:12px;max-width:220px;overflow:hidden;text-overflow:ellipsis}.location nav span{color:#c1ccc4}.toolbar{display:flex;gap:8px;align-items:center;margin:18px 0}.toolbar input[type=search]{flex:1;min-width:0}.toolbar button{font-size:12px;padding:7px 9px}#selection-count{font-size:11px;color:#819286;white-space:nowrap}.table-wrap{overflow-x:auto;min-height:290px}table{width:100%;border-collapse:collapse;table-layout:fixed}th{text-align:left;font-size:11px;color:#8a978e;font-weight:500;border-bottom:1px solid #e3e9e4;padding:11px 9px}td{padding:12px 9px;border-bottom:1px solid #f0f3f0;font-size:12px;color:#79897e}.check-cell{width:30px;padding-left:0}.size-cell{width:82px;text-align:right;font-variant-numeric:tabular-nums}.date-cell{width:145px;text-align:right}tr:hover td{background:#f7faf7}tr.active td{background:#edf5ee}td .entry{border:0;background:transparent;padding:0;display:flex;align-items:center;gap:10px;max-width:100%;color:#354e3e;font-size:13px;text-align:left}td .entry span:last-child{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.file-icon{display:inline-block;width:13px;height:16px;border:1px solid #a8b8ad;background:#f5f8f5;border-radius:2px;flex-shrink:0}.empty{text-align:center;padding:65px 20px;color:#8b9b8f;line-height:1.9}.list-footer{border-top:1px solid #e9eee9;display:flex;align-items:center;justify-content:space-between;color:#92a095;font-size:11px;padding:13px 0;margin-top:auto;min-height:48px}.preview-panel{border-left:1px solid #dbe3de;display:flex;flex-direction:column;padding:29px 20px 20px;background:#f8faf7;min-width:0}.preview-heading{display:flex;justify-content:space-between;align-items:center}.preview-heading h2{font-size:13px;color:#61776a}.preview-body{padding-top:25px;flex:1;min-width:0}.preview-empty{text-align:center;color:#859889;padding:80px 0;line-height:2}.preview-empty small{color:#a0aca2;font-size:11px}.preview-body h3{font-size:15px;line-height:1.7;overflow-wrap:anywhere;font-weight:500;margin:0 0 18px}.preview-body dl{font-size:11px;display:grid;grid-template-columns:60px minmax(0,1fr);gap:10px;margin:20px 0;color:#91a094}.preview-body dd{margin:0;color:#607968;overflow-wrap:anywhere}.preview-body pre{font:11px/1.8 ui-monospace,SFMono-Regular,monospace;white-space:pre-wrap;overflow-wrap:anywhere;max-height:50vh;overflow:auto;background:#edf2ec;padding:12px;border-radius:5px;color:#48654e}.preview-body img{max-width:100%;max-height:40vh;object-fit:contain;border-radius:4px}.preview-body p{font-size:12px;line-height:1.8;color:#8c9a8f}.preview-actions{display:flex;gap:8px;padding-top:20px}.preview-actions button{flex:1;font-size:12px}.transfer{border-top:1px solid #dce8df;padding:14px 0;font-size:12px}.transfer>div{display:flex;align-items:center;justify-content:space-between}.transfer progress{width:100%;height:5px;accent-color:#227b54;margin:10px 0}.transfer span{font-size:11px;color:#7b9082}dialog{border:1px solid #d4ded6;border-radius:10px;padding:26px;max-width:min(480px,90vw);color:#344c3c;box-shadow:0 20px 80px #182c2530}dialog::backdrop{background:#1c322747}dialog h2{font-size:19px;margin-bottom:15px}dialog p{font-size:13px;line-height:1.8;color:#879489}dialog ul{max-height:180px;overflow:auto;padding-left:20px;font-size:12px;line-height:1.9;overflow-wrap:anywhere}.dialog-actions{display:flex;justify-content:flex-end;gap:10px;margin-top:24px}[hidden]{display:none!important}@media(min-width:1500px){.workspace{grid-template-columns:235px minmax(500px,1fr) 370px}.files{padding-left:38px;padding-right:38px}}@media(max-width:1100px){.workspace{grid-template-columns:160px minmax(360px,1fr) 260px}.files{padding:24px 18px 0}.authorization{flex-wrap:wrap;gap:10px}.grant-field{flex-basis:100%}.session-controls{margin-left:auto}.date-cell{width:110px}.toolbar{flex-wrap:wrap}.toolbar input[type=search]{flex-basis:100%}}@media(max-width:820px){.workspace{grid-template-columns:1fr}.sidebar{display:none}.preview-panel{border-left:0;border-top:1px solid #dbe3de}.preview-empty{padding:20px}.files{min-height:60vh}.authorization{padding:14px 18px}.grant-field{gap:7px;flex-wrap:wrap}.grant-field select{flex:1;min-width:180px}.session-controls{width:100%;justify-content:space-between;gap:8px}.expiry{gap:6px}.topbar{padding:0 18px}.topnote{display:none}.date-cell{width:110px}.preview-body pre{max-height:280px}.preview-actions{max-width:360px}}
|
|
14
|
+
/* Independent scrolling keeps file actions within the current viewport. */
|
|
15
|
+
body{height:100vh;height:100dvh;display:flex;flex-direction:column;overflow:hidden}
|
|
16
|
+
.topbar,.authorization,.notice{flex-shrink:0}.notice{max-height:20vh;overflow:auto}
|
|
17
|
+
.workspace{flex:1;min-height:0;overflow:hidden}.sidebar{min-height:0;overflow:auto}
|
|
18
|
+
.files{min-height:0;overflow:hidden}.files>:not(.table-wrap){flex-shrink:0}
|
|
19
|
+
.table-wrap{flex:1;min-height:0;overflow:auto;overscroll-behavior:contain}
|
|
20
|
+
.table-wrap thead{position:sticky;top:0;background:#fff;z-index:1}
|
|
21
|
+
.list-footer{margin-top:0;flex-shrink:0}.preview-panel{min-height:0;overflow:hidden}
|
|
22
|
+
.preview-heading,.preview-actions{flex-shrink:0}.preview-body{min-height:0;overflow:auto;overscroll-behavior:contain;padding-right:6px}
|
|
23
|
+
.preview-actions{border-top:1px solid #dbe3de;margin-top:16px;padding-top:16px;background:#f8faf7}
|
|
24
|
+
.preview-body h4{font-size:12px;font-weight:600;margin:24px 0 12px;color:#496553}
|
|
25
|
+
.preview-body dl{grid-template-columns:78px minmax(0,1fr)}.preview-body dt{overflow-wrap:anywhere}
|
|
26
|
+
.preview-body .metadata-list{grid-template-columns:minmax(0,1fr);gap:5px}.metadata-list dd{padding-bottom:9px}
|
|
27
|
+
.copy-field{display:flex;align-items:flex-start;gap:6px;min-width:0}.copy-field>span{min-width:0;overflow-wrap:anywhere}
|
|
28
|
+
.copy-button{display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;padding:2px;width:24px;height:24px;margin-top:-3px}
|
|
29
|
+
.copy-button svg{width:15px;height:15px}.copy-button.copied{color:#18764e;background:#e1f2e7}
|
|
30
|
+
.copy-field a{color:#197854;text-underline-offset:3px;line-height:1.7}.copy-manual{width:100%;font:inherit}
|
|
31
|
+
.clipboard-fallback{position:fixed;left:0;top:0;opacity:0;pointer-events:none}
|
|
32
|
+
.icon-button{color:#526f5e}.icon-button svg{display:block}.is-loading svg{animation:oss-refresh-spin .8s linear infinite}
|
|
33
|
+
@keyframes oss-refresh-spin{to{transform:rotate(360deg)}}
|
|
34
|
+
@media(prefers-reduced-motion:reduce){.is-loading svg{animation:none}.is-loading{opacity:.55}}
|
|
35
|
+
@media(max-width:820px){.workspace{display:flex;flex-direction:column;overflow:auto}.files{flex:none;height:58dvh;min-height:330px}.preview-panel{flex:none;height:45dvh;min-height:270px}.preview-body pre{max-height:none}}
|
|
36
|
+
|
|
37
|
+
.topbar{height:auto;min-height:62px;flex-wrap:wrap;gap:12px;padding-top:10px;padding-bottom:10px}#service-stop{font-size:12px;background:transparent;border-color:#82958a;color:#edf5ef}.upload-actions{display:flex;gap:8px}.tasks-panel{position:fixed;right:20px;bottom:20px;top:155px;width:min(480px,calc(100vw - 32px));z-index:5;background:#fff;border:1px solid #cbd9cf;border-radius:10px;box-shadow:0 12px 50px #20372e30;display:flex;flex-direction:column;overflow:hidden}.tasks-heading{display:flex;align-items:center;justify-content:space-between;padding:15px 18px;border-bottom:1px solid #e4ebe5}.tasks-note{font-size:12px;line-height:1.8;color:#718577;padding:12px 18px}.tasks-list{overflow:auto;overscroll-behavior:contain;flex:1;min-height:0}.task-card{padding:15px 18px;border-top:1px solid #e8eee9}.task-card h3{font-size:13px;margin:0 0 7px;overflow-wrap:anywhere;font-weight:550}.task-meta,.task-path,.task-stats{font-size:11px;color:#738a7b;line-height:1.7;overflow-wrap:anywhere}.task-path{font-family:ui-monospace,SFMono-Regular,monospace}.task-card progress{width:100%;height:6px;accent-color:#227b54;margin:10px 0 6px}.task-actions{display:flex;gap:7px;margin-top:10px}.task-actions button{font-size:12px;padding:5px 10px}.task-error,#tasks-connection{font-size:12px;color:#9f4b40;line-height:1.7;overflow-wrap:anywhere}.task-error{margin-top:8px}#tasks-connection{padding:0 18px 10px}#tasks-toggle{font-size:12px;background:#2f4b3e;border-color:#607969;color:#edf5ef}#tasks-count{font-variant-numeric:tabular-nums;margin-left:5px}@media(max-width:820px){.tasks-panel{top:140px;right:16px;bottom:16px}.upload-actions{gap:5px}.upload-actions button{font-size:12px;padding:7px 9px}}
|
|
38
|
+
|
|
39
|
+
/* Collapsed rails keep both expand buttons visible and give space back to the file list. */
|
|
40
|
+
.workspace{--sidebar-width:205px;--preview-width:310px;grid-template-columns:var(--sidebar-width) minmax(0,1fr) var(--preview-width)}
|
|
41
|
+
.sidebar-heading{display:flex;align-items:center;justify-content:space-between;gap:6px;flex-shrink:0}.sidebar-heading .eyebrow{letter-spacing:1px;font-size:11px}
|
|
42
|
+
.panel-toggle{width:28px;height:28px;padding:0;flex-shrink:0;font-size:24px;line-height:1}
|
|
43
|
+
.sidebar-content{display:flex;flex-direction:column;flex:1;min-height:0;overflow:auto}.sidebar-content>.scope{padding:0 10px}.sidebar-content .root-button{flex-shrink:0}
|
|
44
|
+
.preview-content{display:flex;flex-direction:column;flex:1;min-height:0;overflow:hidden}
|
|
45
|
+
@media(min-width:1500px){.workspace{--sidebar-width:235px;--preview-width:370px}}
|
|
46
|
+
@media(min-width:821px) and (max-width:1100px){.workspace{--sidebar-width:160px;--preview-width:260px}}
|
|
47
|
+
.workspace[data-sidebar-collapsed=true]{--sidebar-width:44px}.workspace[data-preview-collapsed=true]{--preview-width:44px}
|
|
48
|
+
.workspace[data-sidebar-collapsed=true] .sidebar,.workspace[data-preview-collapsed=true] .preview-panel{padding:20px 7px;overflow:hidden}
|
|
49
|
+
.workspace[data-sidebar-collapsed=true] .sidebar-heading,.workspace[data-preview-collapsed=true] .preview-heading{flex-direction:column-reverse;gap:16px}
|
|
50
|
+
.workspace[data-sidebar-collapsed=true] .sidebar-heading h2,.workspace[data-preview-collapsed=true] .preview-heading h2{writing-mode:vertical-rl;letter-spacing:2px;font-size:11px;padding:0;font-weight:500}
|
|
51
|
+
@media(max-width:820px){
|
|
52
|
+
.sidebar{display:flex;flex:none;padding:12px 18px;max-height:38dvh;border-right:0;border-bottom:1px solid #dbe3de}.sidebar-content{flex:auto}.sidebar-bottom{padding-top:16px}.sidebar-heading .eyebrow{padding-left:0}
|
|
53
|
+
.workspace[data-sidebar-collapsed=true] .sidebar,.workspace[data-preview-collapsed=true] .preview-panel{height:auto;min-height:0;max-height:none;padding:8px 18px}
|
|
54
|
+
.workspace[data-sidebar-collapsed=true] .sidebar-heading,.workspace[data-preview-collapsed=true] .preview-heading{flex-direction:row;gap:8px}
|
|
55
|
+
.workspace[data-sidebar-collapsed=true] .sidebar-heading h2,.workspace[data-preview-collapsed=true] .preview-heading h2{writing-mode:horizontal-tb;letter-spacing:1px}
|
|
56
|
+
}
|
|
57
|
+
`;
|
|
58
|
+
//# sourceMappingURL=file-workspace-style.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-workspace-style.js","sourceRoot":"","sources":["../../src/local-web/file-workspace-style.ts"],"names":[],"mappings":"AAAA,qFAAqF;AACrF,MAAM,CAAC,MAAM,kBAAkB,GAAG,MAAM,CAAC,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAuD3C,CAAC"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/** Shared file-list and transfer-card components. Business adapters supply labels and actions. */
|
|
2
|
+
export const FILE_WORKSPACE_JS = String.raw `
|
|
3
|
+
function workspaceNode(tag, text, className) {
|
|
4
|
+
const element=document.createElement(tag);
|
|
5
|
+
if(text!==undefined)element.textContent=String(text);
|
|
6
|
+
if(className)element.className=className;
|
|
7
|
+
return element;
|
|
8
|
+
}
|
|
9
|
+
function workspaceFileRow(options) {
|
|
10
|
+
const row=workspaceNode('tr');row.tabIndex=0;
|
|
11
|
+
if(options.selected)row.className='active';
|
|
12
|
+
row.oncontextmenu=event=>options.onMenu(event);
|
|
13
|
+
row.onkeydown=event=>{if(event.key==='ContextMenu'||event.shiftKey&&event.key==='F10')options.onMenu(event,row);};
|
|
14
|
+
if(options.leading)row.append(options.leading);
|
|
15
|
+
const cell=workspaceNode('td'),button=workspaceNode('button',undefined,'entry');button.title=options.title||options.name;
|
|
16
|
+
button.append(workspaceNode('span',undefined,options.icon||'file-icon'),workspaceNode('span',options.name));
|
|
17
|
+
button.onclick=options.onOpen;cell.append(button);row.append(cell);
|
|
18
|
+
for(const [text,className] of options.cells)row.append(workspaceNode('td',text,className));
|
|
19
|
+
return row;
|
|
20
|
+
}
|
|
21
|
+
function createWorkspaceTransferCard(id, onAction, labels={pause:'暂停',resume:'恢复',cancel:'取消'}) {
|
|
22
|
+
const root=workspaceNode('article',undefined,'task-card'),title=workspaceNode('h3'),meta=workspaceNode('p',undefined,'task-meta'),path=workspaceNode('p',undefined,'task-path'),progress=workspaceNode('progress'),stats=workspaceNode('p',undefined,'task-stats'),error=workspaceNode('p',undefined,'task-error'),buttons=workspaceNode('div',undefined,'task-actions'),extra=workspaceNode('div',undefined,'task-ingestion');
|
|
23
|
+
progress.max=100;progress.setAttribute('aria-label','文件传输进度');
|
|
24
|
+
const actions=new Map();
|
|
25
|
+
for(const action of ['pause','resume','cancel']){const button=workspaceNode('button',labels[action]);button.onclick=()=>onAction(id,action);actions.set(action,button);buttons.append(button);}
|
|
26
|
+
root.append(title,meta,path,progress,stats,error,extra,buttons);
|
|
27
|
+
return {root,title,meta,path,progress,stats,error,extra,actions};
|
|
28
|
+
}
|
|
29
|
+
function updateWorkspaceTransferCard(card, job, presentation, busy=false) {
|
|
30
|
+
const text=(element,value)=>{if(element.textContent!==value)element.textContent=value;};
|
|
31
|
+
text(card.title,presentation.title);text(card.meta,presentation.meta);text(card.path,job.localPath||'');card.path.title=job.localPath||'';
|
|
32
|
+
card.progress.value=job.size>0?Math.min(100,job.transferred/job.size*100):job.status==='completed'?100:0;
|
|
33
|
+
card.progress.setAttribute('aria-valuetext',presentation.progress);
|
|
34
|
+
text(card.stats,presentation.stats);text(card.error,job.error||'');card.error.hidden=!job.error;
|
|
35
|
+
const available={pause:['queued','running'].includes(job.status),resume:['paused','failed'].includes(job.status),cancel:['queued','running','paused','failed'].includes(job.status)};
|
|
36
|
+
for(const [action,button] of card.actions){button.hidden=!available[action];button.disabled=busy;}
|
|
37
|
+
}
|
|
38
|
+
`;
|
|
39
|
+
//# sourceMappingURL=file-workspace.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-workspace.js","sourceRoot":"","sources":["../../src/local-web/file-workspace.ts"],"names":[],"mappings":"AAAA,kGAAkG;AAClG,MAAM,CAAC,MAAM,iBAAiB,GAAG,MAAM,CAAC,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAoC1C,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { ServerResponse, IncomingMessage } from 'node:http';
|
|
2
|
+
import type { Readable } from 'node:stream';
|
|
3
|
+
export declare function localWebHeaders(res: ServerResponse, contentType: string): void;
|
|
4
|
+
export declare function strictLocalJson(req: Readable, allowedKeys: readonly string[]): Promise<Record<string, unknown>>;
|
|
5
|
+
export declare function requireLocalOrigin(req: IncomingMessage, origin: string, allowDocumentNavigation?: boolean): void;
|
|
6
|
+
export declare function requireLocalAuthorization(req: IncomingMessage, origin: string, token: string): void;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { timingSafeEqual } from 'node:crypto';
|
|
2
|
+
import { OssError } from '../oss/errors.js';
|
|
3
|
+
export function localWebHeaders(res, contentType) {
|
|
4
|
+
res.setHeader("Content-Type", contentType);
|
|
5
|
+
res.setHeader("Cache-Control", "no-store");
|
|
6
|
+
res.setHeader("X-Content-Type-Options", "nosniff");
|
|
7
|
+
res.setHeader("Referrer-Policy", "no-referrer");
|
|
8
|
+
res.setHeader("X-Frame-Options", "DENY");
|
|
9
|
+
res.setHeader("Content-Security-Policy", "default-src 'none'; script-src 'self'; style-src 'self'; connect-src 'self'; img-src 'self' data:; frame-ancestors 'none'; base-uri 'none'; form-action 'none'");
|
|
10
|
+
}
|
|
11
|
+
export async function strictLocalJson(req, allowedKeys) {
|
|
12
|
+
const chunks = [];
|
|
13
|
+
let size = 0;
|
|
14
|
+
for await (const value of req) {
|
|
15
|
+
const chunk = Buffer.isBuffer(value) ? value : Buffer.from(value);
|
|
16
|
+
size += chunk.length;
|
|
17
|
+
if (size > 64 * 1024)
|
|
18
|
+
throw new OssError("Request body too large", "oss_input_invalid", 400);
|
|
19
|
+
chunks.push(chunk);
|
|
20
|
+
}
|
|
21
|
+
let value;
|
|
22
|
+
try {
|
|
23
|
+
value = JSON.parse(Buffer.concat(chunks).toString("utf8"));
|
|
24
|
+
}
|
|
25
|
+
catch {
|
|
26
|
+
throw new OssError("Invalid JSON", "oss_input_invalid", 400);
|
|
27
|
+
}
|
|
28
|
+
if (!value || typeof value !== "object" || Array.isArray(value)
|
|
29
|
+
|| Object.keys(value).some(key => !allowedKeys.includes(key))) {
|
|
30
|
+
throw new OssError("Invalid request fields", "oss_input_invalid", 400);
|
|
31
|
+
}
|
|
32
|
+
return value;
|
|
33
|
+
}
|
|
34
|
+
export function requireLocalOrigin(req, origin, allowDocumentNavigation = false) {
|
|
35
|
+
if (req.headers.host !== new URL(origin).host)
|
|
36
|
+
throw new OssError('Host', 'oss_web_host', 421);
|
|
37
|
+
// An OIDC redirect is a cross-site document navigation. Only callers serving
|
|
38
|
+
// the public HTML shell may opt in; API requests retain the strict check.
|
|
39
|
+
const documentNavigation = allowDocumentNavigation && req.method === 'GET'
|
|
40
|
+
&& req.headers['sec-fetch-mode'] === 'navigate' && req.headers['sec-fetch-dest'] === 'document';
|
|
41
|
+
if ((req.headers.origin && req.headers.origin !== origin) || (req.headers['sec-fetch-site'] === 'cross-site' && !documentNavigation))
|
|
42
|
+
throw new OssError('Origin', 'oss_web_origin', 403);
|
|
43
|
+
}
|
|
44
|
+
export function requireLocalAuthorization(req, origin, token) {
|
|
45
|
+
const bearer = req.headers.authorization ?? '', expected = `Bearer ${token}`;
|
|
46
|
+
if (Buffer.byteLength(bearer) !== Buffer.byteLength(expected) || !timingSafeEqual(Buffer.from(bearer), Buffer.from(expected)))
|
|
47
|
+
throw new OssError('Token', 'oss_web_unauthorized', 401);
|
|
48
|
+
if (!['GET', 'HEAD'].includes(req.method ?? '') && req.headers.origin !== origin)
|
|
49
|
+
throw new OssError('Origin', 'oss_web_origin', 403);
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=security.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"security.js","sourceRoot":"","sources":["../../src/local-web/security.ts"],"names":[],"mappings":"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"}
|
package/dist/login-recovery.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/** Keep recovery in the same explicitly selected identity source. */
|
|
2
2
|
export function loginRecoveryCommand(args) {
|
|
3
|
+
let environment;
|
|
3
4
|
let issuer;
|
|
4
5
|
let service;
|
|
5
6
|
let root;
|
|
@@ -7,7 +8,11 @@ export function loginRecoveryCommand(args) {
|
|
|
7
8
|
for (let i = 0; i < args.length; i++) {
|
|
8
9
|
if (args[i] === "--")
|
|
9
10
|
break;
|
|
10
|
-
if (args[i] === "--
|
|
11
|
+
if (args[i] === "--environment")
|
|
12
|
+
environment = args[++i];
|
|
13
|
+
else if (args[i]?.startsWith("--environment="))
|
|
14
|
+
environment = args[i].slice("--environment=".length);
|
|
15
|
+
else if (args[i] === "--issuer")
|
|
11
16
|
issuer = args[++i];
|
|
12
17
|
else if (args[i]?.startsWith("--issuer="))
|
|
13
18
|
issuer = args[i].slice("--issuer=".length);
|
|
@@ -20,10 +25,10 @@ export function loginRecoveryCommand(args) {
|
|
|
20
25
|
else if (!root && !args[i]?.startsWith("-"))
|
|
21
26
|
root = args[i];
|
|
22
27
|
}
|
|
28
|
+
const quote = (value) => /^[A-Za-z0-9_.:/-]+$/u.test(value) ? value : "'" + value.replace(/'/gu, "'\\''") + "'";
|
|
23
29
|
if (root === "kb" || service === "kb") {
|
|
24
|
-
return "numa login --service kb --no-console --no-config";
|
|
30
|
+
return "numa login --service kb --no-console --no-config" + (issuer ? ` --issuer ${quote(issuer)}` : "") + (environment ? ` --environment ${quote(environment)}` : "");
|
|
25
31
|
}
|
|
26
|
-
const quote = (value) => /^[A-Za-z0-9_.:/-]+$/u.test(value) ? value : "'" + value.replace(/'/gu, "'\\''") + "'";
|
|
27
32
|
return "numa login --no-console --no-config" + (issuer ? ` --issuer ${quote(issuer)}` : platform ? " --platform" : "");
|
|
28
33
|
}
|
|
29
34
|
//# sourceMappingURL=login-recovery.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"login-recovery.js","sourceRoot":"","sources":["../src/login-recovery.ts"],"names":[],"mappings":"AAAA,qEAAqE;AACrE,MAAM,UAAU,oBAAoB,CAAC,IAAc;IACjD,IAAI,MAA0B,CAAC;IAC/B,IAAI,OAA2B,CAAC;IAChC,IAAI,IAAwB,CAAC;IAC7B,IAAI,QAAQ,GAAG,KAAK,CAAC;IACrB,KAAK,IAAI,CAAC,GAAC,CAAC,EAAC,CAAC,GAAC,IAAI,CAAC,MAAM,EAAC,CAAC,EAAE,EAAE,CAAC;QAC/B,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI;YAAE,MAAM;QAC5B,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,UAAU;YAAE,MAAM,GAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"login-recovery.js","sourceRoot":"","sources":["../src/login-recovery.ts"],"names":[],"mappings":"AAAA,qEAAqE;AACrE,MAAM,UAAU,oBAAoB,CAAC,IAAc;IACjD,IAAI,WAA+B,CAAC;IACpC,IAAI,MAA0B,CAAC;IAC/B,IAAI,OAA2B,CAAC;IAChC,IAAI,IAAwB,CAAC;IAC7B,IAAI,QAAQ,GAAG,KAAK,CAAC;IACrB,KAAK,IAAI,CAAC,GAAC,CAAC,EAAC,CAAC,GAAC,IAAI,CAAC,MAAM,EAAC,CAAC,EAAE,EAAE,CAAC;QAC/B,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI;YAAE,MAAM;QAC5B,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,eAAe;YAAE,WAAW,GAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;aAClD,IAAI,IAAI,CAAC,CAAC,CAAC,EAAE,UAAU,CAAC,gBAAgB,CAAC;YAAE,WAAW,GAAC,IAAI,CAAC,CAAC,CAAE,CAAC,KAAK,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC;aAC/F,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,UAAU;YAAE,MAAM,GAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;aAC7C,IAAI,IAAI,CAAC,CAAC,CAAC,EAAE,UAAU,CAAC,WAAW,CAAC;YAAE,MAAM,GAAC,IAAI,CAAC,CAAC,CAAE,CAAC,KAAK,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;aAChF,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,WAAW;YAAE,OAAO,GAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;aAC/C,IAAI,IAAI,CAAC,CAAC,CAAC,EAAE,UAAU,CAAC,YAAY,CAAC;YAAE,OAAO,GAAC,IAAI,CAAC,CAAC,CAAE,CAAC,KAAK,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;aACnF,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,YAAY;YAAE,QAAQ,GAAC,IAAI,CAAC;aAC5C,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,UAAU,CAAC,GAAG,CAAC;YAAE,IAAI,GAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC5D,CAAC;IACD,MAAM,KAAK,GAAG,CAAC,KAAY,EAAE,EAAE,CAAC,sBAAsB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,GAAG,KAAK,CAAC,OAAO,CAAC,KAAK,EAAC,OAAO,CAAC,GAAG,GAAG,CAAC;IACtH,IAAI,IAAI,KAAK,IAAI,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;QACtC,OAAO,kDAAkD,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,aAAa,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,kBAAkB,KAAK,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IACzK,CAAC;IACD,OAAO,qCAAqC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,aAAa,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;AACzH,CAAC"}
|
|
@@ -9,6 +9,10 @@ declare const Metadata: z.ZodObject<{
|
|
|
9
9
|
envId: z.ZodString;
|
|
10
10
|
clusterId: z.ZodString;
|
|
11
11
|
gatewayId: z.ZodString;
|
|
12
|
+
catalogMode: z.ZodOptional<z.ZodEnum<{
|
|
13
|
+
NATIVE: "NATIVE";
|
|
14
|
+
ROUTER: "ROUTER";
|
|
15
|
+
}>>;
|
|
12
16
|
default: z.ZodOptional<z.ZodBoolean>;
|
|
13
17
|
publishedEndpoints: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
14
18
|
serviceId: z.ZodString;
|