@xopcai/xopc 0.0.129 → 0.0.131
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/dist/browser-ext/icons/icon-128.png +0 -0
- package/dist/browser-ext/icons/icon-16.png +0 -0
- package/dist/browser-ext/icons/icon-32.png +0 -0
- package/dist/browser-ext/icons/icon-48.png +0 -0
- package/dist/browser-ext/manifest.json +1 -1
- package/dist/extensions/telegram/xopc.extension.json +1 -1
- package/dist/gateway/static/root/apple-touch-icon.png +0 -0
- package/dist/gateway/static/root/assets/{agent-avatar-dicebear-DHzfg5D-.js → agent-avatar-dicebear-BJYeTxQ9.js} +1 -1
- package/dist/gateway/static/root/assets/agents-kVsY4Iz_.js +2 -0
- package/dist/gateway/static/root/assets/app-management-settings-panel-Bj8iJ-7d.js +1 -0
- package/dist/gateway/static/root/assets/{appearance-settings-bYeEj3IW.js → appearance-settings-6TjISbHB.js} +1 -1
- package/dist/gateway/static/root/assets/apps-page-DC4YwXLL.js +1 -0
- package/dist/gateway/static/root/assets/{archive-plugin-Dy6lsTHw.js → archive-plugin-2G62raBg.js} +1 -1
- package/dist/gateway/static/root/assets/{attachment-load-qOtBYR6Y.js → attachment-load-kLNJMEJh.js} +1 -1
- package/dist/gateway/static/root/assets/{automation-suggestion-card-BFH-RfaV.js → automation-suggestion-card-CpcZSSD8.js} +1 -1
- package/dist/gateway/static/root/assets/automations-page-MZ8m4bYP.js +4 -0
- package/dist/gateway/static/root/assets/{binary-plugins-DJvi_thc.js → binary-plugins-C_zSrWow.js} +1 -1
- package/dist/gateway/static/root/assets/{block-editor-DlMnizlt.js → block-editor-D_PMrT-l.js} +4 -4
- package/dist/gateway/static/root/assets/browser-settings-page-C89wKfPd.js +8 -0
- package/dist/gateway/static/root/assets/capability-presets-api-CPFtajl7.js +1 -0
- package/dist/gateway/static/root/assets/{capability-presets-settings-panel-Dng8Grpv.js → capability-presets-settings-panel-DWw31-4v.js} +1 -1
- package/dist/gateway/static/root/assets/channel-recipient-api-BUi8syv2.js +1 -0
- package/dist/gateway/static/root/assets/channels-settings-DOYzcMAE.js +1 -0
- package/dist/gateway/static/root/assets/connectors-page-DCE-PgQF.js +2 -0
- package/dist/gateway/static/root/assets/desktop-pet-BYV16wez.js +1 -0
- package/dist/gateway/static/root/assets/{desktop-pet-settings-B-u63N4e.js → desktop-pet-settings-DGIaFqPR.js} +1 -1
- package/dist/gateway/static/root/assets/{directory-picker-path-field-8p1ehIHn.js → directory-picker-path-field-BEhDuShd.js} +1 -1
- package/dist/gateway/static/root/assets/dreaming-settings-BIkgLFDH.js +3 -0
- package/dist/gateway/static/root/assets/{extension-debug-page-DJ1ABK95.js → extension-debug-page-BIjLZMAQ.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-page-CP9P2lGM.js → extension-page-Cxv4Bgj5.js} +1 -1
- package/dist/gateway/static/root/assets/extension-settings-page-DNd0tRFl.js +1 -0
- package/dist/gateway/static/root/assets/fetch-Bl7zMnmd.js +1 -0
- package/dist/gateway/static/root/assets/gateway-config-api-BiqKIkkp.js +1 -0
- package/dist/gateway/static/root/assets/gateway-settings-D_Cvasqi.js +1 -0
- package/dist/gateway/static/root/assets/{gateway-startup-retry-CY5W2Pp4.js → gateway-startup-retry-CPOgTcpv.js} +1 -1
- package/dist/gateway/static/root/assets/{goal-create-dialog-2lPbGfp3.js → goal-create-dialog-DZ68qzpm.js} +1 -1
- package/dist/gateway/static/root/assets/goal-detail-page-DF8QhTHH.js +4 -0
- package/dist/gateway/static/root/assets/goals-config-api-h26_-2Vm.js +1 -0
- package/dist/gateway/static/root/assets/goals-page-BzBKHZJg.js +2 -0
- package/dist/gateway/static/root/assets/goals-settings-BFG1uTI8.js +1 -0
- package/dist/gateway/static/root/assets/heartbeat-settings-5vV8vTva.js +1 -0
- package/dist/gateway/static/root/assets/index-DOetFpTt.js +262 -0
- package/dist/gateway/static/root/assets/index-W4ogAiHt.css +1 -0
- package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-BrENZzM7.js → keyboard-shortcuts-settings-Dpx1ovO6.js} +1 -1
- package/dist/gateway/static/root/assets/logs-page-3QO3elfx.js +7 -0
- package/dist/gateway/static/root/assets/{markdown-split-BYF4ReGM.js → markdown-split-Ba4EsPkV.js} +1 -1
- package/dist/gateway/static/root/assets/{media-plugins-CpQDz-QJ.js → media-plugins-lA5rvtCq.js} +1 -1
- package/dist/gateway/static/root/assets/{messages-YzjnURPJ.js → messages-Bq4REfIj.js} +2 -2
- package/dist/gateway/static/root/assets/models-hub-panel-BBG87CHZ.js +2 -0
- package/dist/gateway/static/root/assets/notes-page-DrUGE-Hn.js +1 -0
- package/dist/gateway/static/root/assets/notes-workbench-eAIE8iKV.js +2 -0
- package/dist/gateway/static/root/assets/{page-tabs-RnYYOIWO.js → page-tabs-Cy7bX7Ce.js} +1 -1
- package/dist/gateway/static/root/assets/{preview-open-alternatives-CTRt06Ri.js → preview-open-alternatives-B9_iql49.js} +1 -1
- package/dist/gateway/static/root/assets/project-detail-page-Cwct6pCV.js +1 -0
- package/dist/gateway/static/root/assets/projects-page-BXZlzV8t.js +1 -0
- package/dist/gateway/static/root/assets/remote-access-hub-C29EWM0P.js +1 -0
- package/dist/gateway/static/root/assets/{save-bar-controls-c4pZeikq.js → save-bar-controls-nMloZ0mp.js} +1 -1
- package/dist/gateway/static/root/assets/{schedule-field-Cb6R7iuP.js → schedule-field-BuajpVNF.js} +1 -1
- package/dist/gateway/static/root/assets/{schema-form-BqET_hEP.js → schema-form-IeXV_yQk.js} +1 -1
- package/dist/gateway/static/root/assets/sessions-page-DHHVDqsy.js +1 -0
- package/dist/gateway/static/root/assets/settings-advanced-gate-hDvmobsT.js +1 -0
- package/dist/gateway/static/root/assets/{settings-collapsible-section-DuOvqNsI.js → settings-collapsible-section-ByixWwvu.js} +1 -1
- package/dist/gateway/static/root/assets/{settings-form-section-DptSsbWd.js → settings-form-section-C-5-n-jM.js} +1 -1
- package/dist/gateway/static/root/assets/{settings-loading-skeleton-BlVfBCb9.js → settings-loading-skeleton-CTA5Gje4.js} +1 -1
- package/dist/gateway/static/root/assets/settings-page-DzqxeemF.js +1 -0
- package/dist/gateway/static/root/assets/{settings-page-layout-DVt69dJJ.js → settings-page-layout-DgFTf6nM.js} +1 -1
- package/dist/gateway/static/root/assets/setup-status-panel-svpHcJ62.js +1 -0
- package/dist/gateway/static/root/assets/share-preview-page-IOjU69FC.js +2 -0
- package/dist/gateway/static/root/assets/shares-settings-Ddg8gHPN.js +1 -0
- package/dist/gateway/static/root/assets/skill-reload-api-DcNOEJsK.js +1 -0
- package/dist/gateway/static/root/assets/skills-page-DoonnYRs.js +2 -0
- package/dist/gateway/static/root/assets/{system-settings-panel-CW22OkZ4.js → system-settings-panel-BMDD7FXg.js} +1 -1
- package/dist/gateway/static/root/assets/{typed-models-lib-BqpGAKxV.js → typed-models-lib-DayamJ56.js} +1 -1
- package/dist/gateway/static/root/assets/use-channel-catalog-ChYwFiqo.js +1 -0
- package/dist/gateway/static/root/assets/{user-profile-settings-panel-CERVLuaW.js → user-profile-settings-panel-Dd0X3mPv.js} +1 -1
- package/dist/gateway/static/root/assets/{utils-BnmysurA.js → utils-D9v9ZpK4.js} +1 -1
- package/dist/gateway/static/root/assets/voice-api-key-field-QXGvjTwa.js +1 -0
- package/dist/gateway/static/root/assets/work-item-detail-page-CP-5OUYI.js +1 -0
- package/dist/gateway/static/root/assets/{workflow-run-setup-panel-Ci9GSPnS.js → workflow-run-setup-panel-IidqhbUI.js} +2 -2
- package/dist/gateway/static/root/assets/{workflow-start-dialog-BhDj8pqH.js → workflow-start-dialog-BQQkr8YD.js} +1 -1
- package/dist/gateway/static/root/assets/workflows-page-DtVIjVSX.js +18 -0
- package/dist/gateway/static/root/favicon-16x16.png +0 -0
- package/dist/gateway/static/root/favicon-32x32.png +0 -0
- package/dist/gateway/static/root/favicon-icon.svg +23 -1
- package/dist/gateway/static/root/favicon.ico +0 -0
- package/dist/gateway/static/root/favicon.png +0 -0
- package/dist/gateway/static/root/favicon.svg +20 -24
- package/dist/gateway/static/root/index.html +11 -11
- package/dist/gateway/static/root/logo-dark.svg +18 -23
- package/dist/gateway/static/root/logo.svg +18 -24
- package/dist/gateway/static/root/pwa-192x192.png +0 -0
- package/dist/gateway/static/root/pwa-512x512.png +0 -0
- package/dist/gateway/static/root/site.webmanifest +23 -0
- package/dist/package.js +1 -1
- package/dist/src/cli/commands/gateway/probe.js +6 -6
- package/dist/src/cli/commands/gateway/probe.js.map +1 -1
- package/dist/src/cli/commands/onboard.js +2 -2
- package/dist/src/cli/commands/onboard.js.map +1 -1
- package/dist/src/cli/commands/tui.js +11 -4
- package/dist/src/cli/commands/tui.js.map +1 -1
- package/dist/src/cli/utils/gateway-client-options.d.ts +3 -0
- package/dist/src/cli/utils/gateway-client-options.js +2 -1
- package/dist/src/cli/utils/gateway-client-options.js.map +1 -1
- package/dist/src/cli/utils/gateway-client.d.ts +6 -3
- package/dist/src/cli/utils/gateway-client.js +14 -8
- package/dist/src/cli/utils/gateway-client.js.map +1 -1
- package/dist/src/gateway/credential.d.ts +9 -0
- package/dist/src/gateway/credential.js +16 -0
- package/dist/src/gateway/credential.js.map +1 -0
- package/dist/src/gateway/hono/app.d.ts +0 -1
- package/dist/src/gateway/hono/app.js +2 -9
- package/dist/src/gateway/hono/app.js.map +1 -1
- package/dist/src/gateway/hono/middleware/auth.d.ts +0 -2
- package/dist/src/gateway/hono/middleware/auth.js +46 -21
- package/dist/src/gateway/hono/middleware/auth.js.map +1 -1
- package/dist/src/gateway/hono/routes/sessions.js +2 -27
- package/dist/src/gateway/hono/routes/sessions.js.map +1 -1
- package/dist/src/gateway/server.js +1 -5
- package/dist/src/gateway/server.js.map +1 -1
- package/dist/src/mcp/channel-bridge.d.ts +2 -1
- package/dist/src/mcp/channel-bridge.js +10 -6
- package/dist/src/mcp/channel-bridge.js.map +1 -1
- package/dist/src/mcp/channel-server.d.ts +2 -1
- package/dist/src/mcp/channel-server.js +1 -1
- package/dist/src/mcp/channel-server.js.map +1 -1
- package/dist/src/mcp/gateway-http-client.d.ts +3 -2
- package/dist/src/mcp/gateway-http-client.js +9 -7
- package/dist/src/mcp/gateway-http-client.js.map +1 -1
- package/dist/src/tui/backends/gateway-sse-backend.d.ts +3 -2
- package/dist/src/tui/backends/gateway-sse-backend.js +45 -41
- package/dist/src/tui/backends/gateway-sse-backend.js.map +1 -1
- package/dist/src/tui/tui-types.d.ts +3 -2
- package/dist/src/tui/tui-types.js.map +1 -1
- package/dist/src/tui/tui.js +1 -1
- package/dist/src/tui/tui.js.map +1 -1
- package/package.json +5 -2
- package/dist/gateway/static/root/assets/agents-CMxKKFQD.js +0 -2
- package/dist/gateway/static/root/assets/app-management-settings-panel-ptk9c5BN.js +0 -1
- package/dist/gateway/static/root/assets/apps-page-DdZvDf5B.js +0 -1
- package/dist/gateway/static/root/assets/automations-page-B8JTjkCr.js +0 -4
- package/dist/gateway/static/root/assets/browser-settings-page-slHLiZgi.js +0 -8
- package/dist/gateway/static/root/assets/capability-presets-api-D4q7vHVJ.js +0 -1
- package/dist/gateway/static/root/assets/channel-recipient-api-BrW5Kcgc.js +0 -1
- package/dist/gateway/static/root/assets/channels-settings-KIsISXw0.js +0 -1
- package/dist/gateway/static/root/assets/connectors-page-C5fx4Qs9.js +0 -2
- package/dist/gateway/static/root/assets/desktop-pet-Jmdn6q47.js +0 -1
- package/dist/gateway/static/root/assets/dreaming-settings-CCkKP-I4.js +0 -3
- package/dist/gateway/static/root/assets/extension-settings-page-DnhU-tx0.js +0 -1
- package/dist/gateway/static/root/assets/fetch-BMjlW0g1.js +0 -1
- package/dist/gateway/static/root/assets/gateway-config-api-CjxDn46s.js +0 -1
- package/dist/gateway/static/root/assets/gateway-settings-TING7224.js +0 -1
- package/dist/gateway/static/root/assets/goal-detail-page-DHWVRafk.js +0 -4
- package/dist/gateway/static/root/assets/goals-config-api-BqhuxG8P.js +0 -1
- package/dist/gateway/static/root/assets/goals-page-CMk-9ZYN.js +0 -2
- package/dist/gateway/static/root/assets/goals-settings-BHzOAU_l.js +0 -1
- package/dist/gateway/static/root/assets/heartbeat-settings-BQIm0P3V.js +0 -1
- package/dist/gateway/static/root/assets/index-C4k6QSXw.js +0 -257
- package/dist/gateway/static/root/assets/index-EKmpPvZj.css +0 -1
- package/dist/gateway/static/root/assets/logs-page-BiL302Ve.js +0 -2
- package/dist/gateway/static/root/assets/models-hub-panel-CFPpl3Cq.js +0 -2
- package/dist/gateway/static/root/assets/notes-page-BurgcdVZ.js +0 -1
- package/dist/gateway/static/root/assets/notes-workbench-BAELRM_O.js +0 -2
- package/dist/gateway/static/root/assets/project-detail-page-iXX1Ceo2.js +0 -1
- package/dist/gateway/static/root/assets/projects-page-GDVTFAY7.js +0 -1
- package/dist/gateway/static/root/assets/remote-access-hub-BUrbUnwv.js +0 -1
- package/dist/gateway/static/root/assets/sessions-page-CiOreA2k.js +0 -1
- package/dist/gateway/static/root/assets/settings-advanced-gate-C-qvptlu.js +0 -1
- package/dist/gateway/static/root/assets/settings-page-xQx2Pkg5.js +0 -1
- package/dist/gateway/static/root/assets/setup-status-panel-DWB8VdLK.js +0 -1
- package/dist/gateway/static/root/assets/share-preview-page-8m_ACH0z.js +0 -2
- package/dist/gateway/static/root/assets/shares-settings-CgxfhNxI.js +0 -1
- package/dist/gateway/static/root/assets/skill-reload-api-BBFUOxmf.js +0 -1
- package/dist/gateway/static/root/assets/skills-page-bo695odu.js +0 -2
- package/dist/gateway/static/root/assets/url-DFGNSBNT.js +0 -1
- package/dist/gateway/static/root/assets/use-channel-catalog-CPdJ0o0i.js +0 -1
- package/dist/gateway/static/root/assets/voice-api-key-field-Jr3jvPcB.js +0 -1
- package/dist/gateway/static/root/assets/work-item-detail-page-B-8rex4u.js +0 -1
- package/dist/gateway/static/root/assets/workflows-page-Brb3UGvs.js +0 -18
package/dist/package.js
CHANGED
|
@@ -20,7 +20,7 @@ function resolveProbeTargets(opts) {
|
|
|
20
20
|
}
|
|
21
21
|
return targets;
|
|
22
22
|
}
|
|
23
|
-
async function probeTarget(callGatewayApi, target,
|
|
23
|
+
async function probeTarget(callGatewayApi, target, credential, timeoutMs) {
|
|
24
24
|
const healthResult = await callGatewayApi("GET", "/api/health", {
|
|
25
25
|
url: target.url,
|
|
26
26
|
timeoutMs: timeoutMs ?? 5e3
|
|
@@ -34,9 +34,9 @@ async function probeTarget(callGatewayApi, target, token, timeoutMs) {
|
|
|
34
34
|
error: healthResult.error
|
|
35
35
|
};
|
|
36
36
|
let authenticated = false;
|
|
37
|
-
if (
|
|
37
|
+
if (credential) authenticated = (await callGatewayApi("GET", "/api/status", {
|
|
38
38
|
url: target.url,
|
|
39
|
-
|
|
39
|
+
credential,
|
|
40
40
|
timeoutMs: timeoutMs ?? 5e3
|
|
41
41
|
})).ok;
|
|
42
42
|
return {
|
|
@@ -53,20 +53,20 @@ function createProbeCommand() {
|
|
|
53
53
|
addGatewayClientOptions(cmd);
|
|
54
54
|
cmd.action(async (options) => {
|
|
55
55
|
const configPath = getContextWithOpts().configPath || resolveConfigPath();
|
|
56
|
-
const [{ loadConfig }, { callGatewayApi,
|
|
56
|
+
const [{ loadConfig }, { callGatewayApi, resolveGatewayCredential }] = await Promise.all([import("../../../config/index.js"), import("../../utils/gateway-client.js")]);
|
|
57
57
|
const port = loadConfig(configPath)?.gateway?.port ?? 18790;
|
|
58
58
|
const clientOpts = {
|
|
59
59
|
...parseGatewayClientOptions(options),
|
|
60
60
|
configPath
|
|
61
61
|
};
|
|
62
|
-
const
|
|
62
|
+
const credential = resolveGatewayCredential(clientOpts);
|
|
63
63
|
const targets = resolveProbeTargets({
|
|
64
64
|
url: clientOpts.url,
|
|
65
65
|
port
|
|
66
66
|
});
|
|
67
67
|
const results = [];
|
|
68
68
|
for (const target of targets) {
|
|
69
|
-
const result = await probeTarget(callGatewayApi, target,
|
|
69
|
+
const result = await probeTarget(callGatewayApi, target, credential, clientOpts.timeoutMs);
|
|
70
70
|
results.push(result);
|
|
71
71
|
}
|
|
72
72
|
if (clientOpts.json) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"probe.js","names":[],"sources":["../../../../../src/cli/commands/gateway/probe.ts"],"sourcesContent":["import { Command } from 'commander';\n\nimport { resolveConfigPath } from '../../../config/paths.js';\nimport {
|
|
1
|
+
{"version":3,"file":"probe.js","names":[],"sources":["../../../../../src/cli/commands/gateway/probe.ts"],"sourcesContent":["import { Command } from 'commander';\n\nimport { resolveConfigPath } from '../../../config/paths.js';\nimport { addGatewayClientOptions, parseGatewayClientOptions } from '../../utils/gateway-client-options.js';\nimport { getContextWithOpts } from '../../context.js';\n\ntype GatewayClientModule = typeof import('../../utils/gateway-client.js');\n\ninterface ProbeTarget {\n label: string;\n url: string;\n}\n\ninterface ProbeResultEntry {\n label: string;\n url: string;\n reachable: boolean;\n authenticated: boolean;\n durationMs: number;\n version?: string;\n error?: string;\n}\n\nfunction resolveProbeTargets(opts: { url?: string; port: number }): ProbeTarget[] {\n const targets: ProbeTarget[] = [];\n const port = opts.port;\n targets.push({ label: 'localhost', url: `http://127.0.0.1:${port}` });\n\n if (opts.url) {\n const normalized = opts.url.replace(/\\/+$/, '');\n if (!normalized.includes('127.0.0.1') && !normalized.includes('localhost')) {\n targets.push({ label: 'remote', url: normalized });\n }\n }\n\n return targets;\n}\n\nasync function probeTarget(\n callGatewayApi: GatewayClientModule['callGatewayApi'],\n target: ProbeTarget,\n credential?: import('../../../gateway/credential.js').GatewayCredential,\n timeoutMs?: number,\n): Promise<ProbeResultEntry> {\n const healthResult = await callGatewayApi<{\n status: string;\n version?: string;\n }>('GET', '/api/health', {\n url: target.url,\n timeoutMs: timeoutMs ?? 5000,\n });\n\n if (!healthResult.ok) {\n return {\n label: target.label,\n url: target.url,\n reachable: false,\n authenticated: false,\n durationMs: healthResult.durationMs,\n error: healthResult.error,\n };\n }\n\n let authenticated = false;\n if (credential) {\n const statusResult = await callGatewayApi('GET', '/api/status', {\n url: target.url,\n credential,\n timeoutMs: timeoutMs ?? 5000,\n });\n authenticated = statusResult.ok;\n }\n\n return {\n label: target.label,\n url: target.url,\n reachable: true,\n authenticated,\n durationMs: healthResult.durationMs,\n version: healthResult.data?.version,\n };\n}\n\nexport function createProbeCommand(): Command {\n const cmd = new Command('probe').description('Probe gateway reachability and auth capability');\n\n addGatewayClientOptions(cmd);\n\n cmd.action(async (options) => {\n const ctx = getContextWithOpts();\n const configPath = ctx.configPath || resolveConfigPath();\n const [{ loadConfig }, { callGatewayApi, resolveGatewayCredential }] = await Promise.all([\n import('../../../config/index.js'),\n import('../../utils/gateway-client.js'),\n ]);\n const config = loadConfig(configPath);\n const port = config?.gateway?.port ?? 18790;\n\n const clientOpts = {\n ...parseGatewayClientOptions(options as Record<string, unknown>),\n configPath,\n };\n const credential = resolveGatewayCredential(clientOpts);\n const targets = resolveProbeTargets({ url: clientOpts.url, port });\n const results: ProbeResultEntry[] = [];\n\n for (const target of targets) {\n const result = await probeTarget(callGatewayApi, target, credential, clientOpts.timeoutMs);\n results.push(result);\n }\n\n if (clientOpts.json) {\n console.log(JSON.stringify({ targets: results }, null, 2));\n const anyReachable = results.some((r) => r.reachable);\n process.exit(anyReachable ? 0 : 1);\n }\n\n console.log('🔍 Gateway Probe');\n console.log('');\n\n for (const result of results) {\n if (result.reachable) {\n console.log(`✅ ${result.label} (${result.url})`);\n console.log(` Reachable: yes (${result.durationMs}ms)`);\n console.log(` Auth: ${result.authenticated ? '✅ authenticated' : '🔒 not authenticated (pass --token)'}`);\n if (result.version) {\n console.log(` Version: ${result.version}`);\n }\n } else {\n console.log(`❌ ${result.label} (${result.url})`);\n console.log(' Reachable: no');\n console.log(` Error: ${result.error}`);\n }\n console.log('');\n }\n\n const anyReachable = results.some((r) => r.reachable);\n if (!anyReachable) {\n console.log('💡 Is the gateway running? Try: xopc gateway');\n }\n process.exit(anyReachable ? 0 : 1);\n });\n\n return cmd;\n}\n"],"mappings":";;;;;YAE6D;AAqB7D,SAAS,oBAAoB,MAAqD;CAChF,MAAM,UAAyB,EAAE;CACjC,MAAM,OAAO,KAAK;AAClB,SAAQ,KAAK;EAAE,OAAO;EAAa,KAAK,oBAAoB;EAAQ,CAAC;AAErE,KAAI,KAAK,KAAK;EACZ,MAAM,aAAa,KAAK,IAAI,QAAQ,QAAQ,GAAG;AAC/C,MAAI,CAAC,WAAW,SAAS,YAAY,IAAI,CAAC,WAAW,SAAS,YAAY,CACxE,SAAQ,KAAK;GAAE,OAAO;GAAU,KAAK;GAAY,CAAC;;AAItD,QAAO;;AAGT,eAAe,YACb,gBACA,QACA,YACA,WAC2B;CAC3B,MAAM,eAAe,MAAM,eAGxB,OAAO,eAAe;EACvB,KAAK,OAAO;EACZ,WAAW,aAAa;EACzB,CAAC;AAEF,KAAI,CAAC,aAAa,GAChB,QAAO;EACL,OAAO,OAAO;EACd,KAAK,OAAO;EACZ,WAAW;EACX,eAAe;EACf,YAAY,aAAa;EACzB,OAAO,aAAa;EACrB;CAGH,IAAI,gBAAgB;AACpB,KAAI,WAMF,kBAAgB,MALW,eAAe,OAAO,eAAe;EAC9D,KAAK,OAAO;EACZ;EACA,WAAW,aAAa;EACzB,CAAC,EAC2B;AAG/B,QAAO;EACL,OAAO,OAAO;EACd,KAAK,OAAO;EACZ,WAAW;EACX;EACA,YAAY,aAAa;EACzB,SAAS,aAAa,MAAM;EAC7B;;AAGH,SAAgB,qBAA8B;CAC5C,MAAM,MAAM,IAAI,QAAQ,QAAQ,CAAC,YAAY,iDAAiD;AAE9F,yBAAwB,IAAI;AAE5B,KAAI,OAAO,OAAO,YAAY;EAE5B,MAAM,aADM,oBACU,CAAC,cAAc,mBAAmB;EACxD,MAAM,CAAC,EAAE,cAAc,EAAE,gBAAgB,8BAA8B,MAAM,QAAQ,IAAI,CACvF,OAAO,6BACP,OAAO,iCACR,CAAC;EAEF,MAAM,OADS,WAAW,WACP,EAAE,SAAS,QAAQ;EAEtC,MAAM,aAAa;GACjB,GAAG,0BAA0B,QAAmC;GAChE;GACD;EACD,MAAM,aAAa,yBAAyB,WAAW;EACvD,MAAM,UAAU,oBAAoB;GAAE,KAAK,WAAW;GAAK;GAAM,CAAC;EAClE,MAAM,UAA8B,EAAE;AAEtC,OAAK,MAAM,UAAU,SAAS;GAC5B,MAAM,SAAS,MAAM,YAAY,gBAAgB,QAAQ,YAAY,WAAW,UAAU;AAC1F,WAAQ,KAAK,OAAO;;AAGtB,MAAI,WAAW,MAAM;AACnB,WAAQ,IAAI,KAAK,UAAU,EAAE,SAAS,SAAS,EAAE,MAAM,EAAE,CAAC;GAC1D,MAAM,eAAe,QAAQ,MAAM,MAAM,EAAE,UAAU;AACrD,WAAQ,KAAK,eAAe,IAAI,EAAE;;AAGpC,UAAQ,IAAI,mBAAmB;AAC/B,UAAQ,IAAI,GAAG;AAEf,OAAK,MAAM,UAAU,SAAS;AAC5B,OAAI,OAAO,WAAW;AACpB,YAAQ,IAAI,KAAK,OAAO,MAAM,IAAI,OAAO,IAAI,GAAG;AAChD,YAAQ,IAAI,sBAAsB,OAAO,WAAW,KAAK;AACzD,YAAQ,IAAI,YAAY,OAAO,gBAAgB,oBAAoB,wCAAwC;AAC3G,QAAI,OAAO,QACT,SAAQ,IAAI,eAAe,OAAO,UAAU;UAEzC;AACL,YAAQ,IAAI,KAAK,OAAO,MAAM,IAAI,OAAO,IAAI,GAAG;AAChD,YAAQ,IAAI,mBAAmB;AAC/B,YAAQ,IAAI,aAAa,OAAO,QAAQ;;AAE1C,WAAQ,IAAI,GAAG;;EAGjB,MAAM,eAAe,QAAQ,MAAM,MAAM,EAAE,UAAU;AACrD,MAAI,CAAC,aACH,SAAQ,IAAI,+CAA+C;AAE7D,UAAQ,KAAK,eAAe,IAAI,EAAE;GAClC;AAEF,QAAO"}
|
|
@@ -89,11 +89,11 @@ async function runOnboard(options, ctx) {
|
|
|
89
89
|
const displayHost = resolveGatewayLocalClientHost(config);
|
|
90
90
|
const gwToken = gatewayConfigured ? gatewayAuth.token : void 0;
|
|
91
91
|
if (Boolean(gatewayConfigured && gwToken && (doGateway || runFullWizard)) && gwToken) {
|
|
92
|
-
const webuiUrl = `http://${displayHost}:${port}
|
|
92
|
+
const webuiUrl = `http://${displayHost}:${port}`;
|
|
93
93
|
console.log("🌐 Web console (browser) — start here");
|
|
94
94
|
console.log(` Open: http://${displayHost}:${port}`);
|
|
95
95
|
console.log(` Token: ${gwToken.slice(0, 8)}...${gwToken.slice(-8)}`);
|
|
96
|
-
console.log("
|
|
96
|
+
console.log(" Open the console and enter the token when prompted:");
|
|
97
97
|
console.log(` ${webuiUrl}`);
|
|
98
98
|
console.log("");
|
|
99
99
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"onboard.js","names":["runModelSetup","runChannelOnboard"],"sources":["../../../../src/cli/commands/onboard.ts"],"sourcesContent":["import { Command } from 'commander';\nimport { select } from '@inquirer/prompts';\nimport { saveConfig } from '../../config/index.js';\nimport { register, formatExamples } from '../registry.js';\nimport type { CLIContext } from '../registry.js';\nimport type { Config } from '../../config/schema.js';\nimport { setupModel as runModelSetup } from './onboard/model.js';\nimport { colors } from '../utils/colors.js';\nimport { setupChannels as runChannelOnboard, getChannelConfigurators } from './onboard/channels/index.js';\nimport { resolveGatewayLocalClientHost } from '../../config/gateway-bind.js';\nimport { initWorkspace } from '../utils/init-workspace.js';\nimport { ConfigSchema } from '../../config/schema.js';\n\nfunction isInteractive(): boolean {\n return process.stdin.isTTY && process.stdout.isTTY;\n}\n\nfunction printGitHubStarHint(): void {\n console.log('\\n⭐ If xopc helps you keep long-term AI work moving, please star the repo:');\n console.log(' https://github.com/xopcai/xopc');\n}\n\nasync function setupNonInteractive(_configPath: string, existingConfig: Config): Promise<Config> {\n console.log('\\n🤖 AI Model Configuration (Non-Interactive Mode)\\n');\n console.log('Current agent manifests:', JSON.stringify(existingConfig.agents?.list ?? [], null, 2));\n console.log('\\n💡 To configure in interactive mode, run: xopc onboard');\n console.log('💡 Or set up manually in:', _configPath);\n return existingConfig;\n}\n\nfunction createOnboardCommand(ctx: CLIContext): Command {\n const cmd = new Command('onboard')\n .description('Interactive setup wizard for xopc (gateway uses schema defaults)')\n .addHelpText(\n 'after',\n formatExamples([\n 'xopc onboard # Full interactive setup',\n 'xopc onboard --quick # Configure model only, then launch locally',\n 'xopc onboard --model # Configure LLM model only',\n 'xopc onboard --channels # Configure messaging channels',\n 'xopc onboard --gateway # Apply default gateway settings (quiet)',\n ])\n )\n .option('--quick', 'Configure model only, then launch locally')\n .option('--model', 'Configure LLM provider and model')\n .option('--channels', 'Configure messaging channels')\n .option('--gateway', 'Configure gateway WebUI')\n .option('--all', 'Configure everything (default)')\n .action(async (options) => {\n try {\n await runOnboard(options, ctx);\n } catch (error: unknown) {\n const err = error as { name?: string; code?: string };\n if (err?.name === 'ExitPromptError' || err?.code === 'EXIT_PROMPT') {\n console.log('\\n\\n👋 Setup cancelled.');\n process.exit(0);\n }\n throw error;\n }\n });\n\n return cmd;\n}\n\ntype OnboardOptions = {\n quick?: boolean;\n model?: boolean;\n channels?: boolean;\n gateway?: boolean;\n all?: boolean;\n};\n\nasync function runOnboard(\n options: OnboardOptions,\n ctx: CLIContext\n): Promise<void> {\n console.log(colors.cyan('\\n🚀 Welcome to xopc setup!\\n'));\n console.log('═'.repeat(50));\n\n const workspacePath = ctx.workspacePath;\n const configPath = ctx.configPath;\n\n const initResult = await initWorkspace({ configPath, workspacePath });\n let config = initResult.config;\n\n // Determine what to configure based on options\n const doModel = options.quick || options.model || options.all || (!options.channels && !options.gateway);\n const doChannels = !options.quick && (options.channels || options.all || (!options.model && !options.gateway));\n const doGateway = !options.quick && (options.gateway || options.all || (!options.model && !options.channels));\n const runFullWizard = !options.quick && !options.model && !options.channels && !options.gateway;\n /** Any setup step besides the unified launch prompt ran in interactive flow. */\n const didConfigurableSteps = doModel || doChannels || doGateway;\n\n if (!isInteractive()) {\n // Non-interactive mode\n if (doModel) {\n config = await setupNonInteractive(configPath, config);\n }\n if (doChannels) {\n console.log('\\n💬 Channels Configuration (Non-Interactive Mode)\\n');\n console.log('💡 To configure channels, edit the config file manually.');\n }\n if (doGateway) {\n console.log('\\n🌐 Gateway Configuration (Non-Interactive Mode)\\n');\n console.log('💡 To configure gateway, edit the config file manually.');\n }\n } else {\n // Interactive mode\n if (doModel) {\n config = await runModelSetup(config, ctx);\n }\n\n if (doChannels) {\n const channelIds = (await getChannelConfigurators(config)).map(c => c.id);\n console.log(colors.gray(`\\nChannel onboarding: ${channelIds.join(', ')}\\n`));\n config = await runChannelOnboard(config);\n }\n\n if (doGateway) {\n config = await setupGateway(config);\n }\n }\n\n // Save config once at the end\n await saveConfig(config as Config, configPath);\n\n console.log('\\n' + '═'.repeat(50));\n console.log('\\n🎉 Setup Complete!\\n');\n\n const gatewayAuth = (config as any)?.gateway?.auth;\n const gatewayConfigured =\n gatewayAuth?.mode === 'token' &&\n typeof gatewayAuth?.token === 'string' &&\n gatewayAuth.token.length > 0;\n const port = (config as Config)?.gateway?.port ?? 18790;\n const displayHost = resolveGatewayLocalClientHost(config as Config);\n const gwToken = gatewayConfigured ? (gatewayAuth.token as string) : undefined;\n\n const showGatewaySummary = Boolean(gatewayConfigured && gwToken && (doGateway || runFullWizard));\n\n if (showGatewaySummary && gwToken) {\n const webuiUrl = `http://${displayHost}:${port}?token=${gwToken}`;\n console.log('🌐 Web console (browser) — start here');\n console.log(` Open: http://${displayHost}:${port}`);\n console.log(` Token: ${gwToken.slice(0, 8)}...${gwToken.slice(-8)}`);\n console.log(' Bookmark link (token is saved in the browser when you open it):');\n console.log(` ${webuiUrl}`);\n console.log('');\n }\n\n if (runFullWizard) {\n console.log('🚀 Next steps:');\n if (gatewayConfigured) {\n console.log(' 1. Choose how to launch below (gateway or terminal UI)');\n console.log(' 2. Or chat with: xopc agent -i');\n } else {\n console.log(' 1. Chat in the terminal: xopc agent -i');\n console.log(' 2. Optional: add the Web console: xopc onboard --gateway');\n }\n console.log('');\n } else if (doGateway && gatewayConfigured) {\n console.log('🚀 Next step:');\n console.log(' Start the gateway if it is not running, then open the Web console URL above.');\n console.log('');\n }\n\n console.log('📝 Usage:');\n console.log(' xopc agent -m \"Hello\" # Chat with AI');\n console.log(' xopc agent -i # Interactive mode');\n console.log(' xopc models list # List models');\n console.log(' xopc config validate # Validate xopc.json');\n console.log(' xopc auth list # View authentication');\n console.log(' xopc init # Full state dirs (if upgrading or missing data)');\n\n console.log('\\n📁 Files:');\n console.log(' Config:', configPath);\n console.log(' Workspace:', workspacePath);\n\n printGitHubStarHint();\n\n if (isInteractive() && didConfigurableSteps) {\n await promptLaunchAfterOnboard(config as Config, ctx, { doChannels });\n }\n\n process.exit(0);\n}\n\nasync function startGatewayAsService(config: Config, ctx: CLIContext): Promise<void> {\n const { startGatewayNow } = await import('./onboard/gateway.js');\n await startGatewayNow(config, ctx);\n}\n\nasync function promptLaunchAfterOnboard(\n config: Config,\n ctx: CLIContext,\n _flags: { doChannels: boolean },\n): Promise<void> {\n console.log('');\n const choice = await select<'tui' | 'gateway' | 'none'>({\n message: 'How do you want to launch xopc now?',\n choices: [\n {\n value: 'tui',\n name: 'Terminal UI (embedded)',\n description: 'xopc — no gateway process required',\n },\n {\n value: 'gateway',\n name: 'Gateway WebUI (OS service)',\n description: 'Install and start the HTTP gateway for the browser console',\n },\n {\n value: 'none',\n name: 'Exit — I will start manually',\n description: 'Finish setup without starting a runtime',\n },\n ],\n default: 'tui',\n });\n\n if (choice === 'gateway') {\n await startGatewayAsService(config, ctx);\n return;\n }\n\n if (choice === 'tui') {\n const { runTui } = await import('../../tui/tui.js');\n await runTui({ local: true });\n return;\n }\n\n console.log('\\n⏭️ You can start later:');\n console.log(' xopc gateway service install');\n console.log(' xopc gateway');\n console.log(' xopc');\n}\n\nasync function setupGateway(config: Config): Promise<Config> {\n console.log(colors.cyan('\\n🌐 Gateway WebUI\\n'));\n console.log(\n colors.gray(\n 'Applying defaults from config schema (127.0.0.1:18790, token auth; token generated if missing).\\n',\n ),\n );\n\n const gw = config.gateway ?? {};\n const { randomBytes } = await import('node:crypto');\n const authMode = gw.auth?.mode === 'none' ? ('none' as const) : ('token' as const);\n const token =\n authMode === 'token'\n ? typeof gw.auth?.token === 'string' && gw.auth.token.length > 0\n ? gw.auth.token\n : randomBytes(24).toString('hex')\n : undefined;\n\n const merged: Config = {\n ...config,\n gateway: {\n ...gw,\n bind: gw.bind ?? 'loopback',\n port: gw.port ?? 18790,\n auth:\n authMode === 'none'\n ? { mode: 'none' as const }\n : { mode: 'token' as const, token: token! },\n },\n };\n\n const parsed = ConfigSchema.parse(merged);\n console.log('✅ Gateway defaults applied.\\n');\n return parsed;\n}\n\nregister({\n id: 'onboard',\n name: 'onboard',\n description: 'Interactive setup wizard',\n factory: createOnboardCommand,\n metadata: {\n category: 'setup',\n examples: ['xopc onboard', 'xopc onboard --model', 'xopc onboard --channels'],\n },\n});\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"onboard.js","names":["runModelSetup","runChannelOnboard"],"sources":["../../../../src/cli/commands/onboard.ts"],"sourcesContent":["import { Command } from 'commander';\nimport { select } from '@inquirer/prompts';\nimport { saveConfig } from '../../config/index.js';\nimport { register, formatExamples } from '../registry.js';\nimport type { CLIContext } from '../registry.js';\nimport type { Config } from '../../config/schema.js';\nimport { setupModel as runModelSetup } from './onboard/model.js';\nimport { colors } from '../utils/colors.js';\nimport { setupChannels as runChannelOnboard, getChannelConfigurators } from './onboard/channels/index.js';\nimport { resolveGatewayLocalClientHost } from '../../config/gateway-bind.js';\nimport { initWorkspace } from '../utils/init-workspace.js';\nimport { ConfigSchema } from '../../config/schema.js';\n\nfunction isInteractive(): boolean {\n return process.stdin.isTTY && process.stdout.isTTY;\n}\n\nfunction printGitHubStarHint(): void {\n console.log('\\n⭐ If xopc helps you keep long-term AI work moving, please star the repo:');\n console.log(' https://github.com/xopcai/xopc');\n}\n\nasync function setupNonInteractive(_configPath: string, existingConfig: Config): Promise<Config> {\n console.log('\\n🤖 AI Model Configuration (Non-Interactive Mode)\\n');\n console.log('Current agent manifests:', JSON.stringify(existingConfig.agents?.list ?? [], null, 2));\n console.log('\\n💡 To configure in interactive mode, run: xopc onboard');\n console.log('💡 Or set up manually in:', _configPath);\n return existingConfig;\n}\n\nfunction createOnboardCommand(ctx: CLIContext): Command {\n const cmd = new Command('onboard')\n .description('Interactive setup wizard for xopc (gateway uses schema defaults)')\n .addHelpText(\n 'after',\n formatExamples([\n 'xopc onboard # Full interactive setup',\n 'xopc onboard --quick # Configure model only, then launch locally',\n 'xopc onboard --model # Configure LLM model only',\n 'xopc onboard --channels # Configure messaging channels',\n 'xopc onboard --gateway # Apply default gateway settings (quiet)',\n ])\n )\n .option('--quick', 'Configure model only, then launch locally')\n .option('--model', 'Configure LLM provider and model')\n .option('--channels', 'Configure messaging channels')\n .option('--gateway', 'Configure gateway WebUI')\n .option('--all', 'Configure everything (default)')\n .action(async (options) => {\n try {\n await runOnboard(options, ctx);\n } catch (error: unknown) {\n const err = error as { name?: string; code?: string };\n if (err?.name === 'ExitPromptError' || err?.code === 'EXIT_PROMPT') {\n console.log('\\n\\n👋 Setup cancelled.');\n process.exit(0);\n }\n throw error;\n }\n });\n\n return cmd;\n}\n\ntype OnboardOptions = {\n quick?: boolean;\n model?: boolean;\n channels?: boolean;\n gateway?: boolean;\n all?: boolean;\n};\n\nasync function runOnboard(\n options: OnboardOptions,\n ctx: CLIContext\n): Promise<void> {\n console.log(colors.cyan('\\n🚀 Welcome to xopc setup!\\n'));\n console.log('═'.repeat(50));\n\n const workspacePath = ctx.workspacePath;\n const configPath = ctx.configPath;\n\n const initResult = await initWorkspace({ configPath, workspacePath });\n let config = initResult.config;\n\n // Determine what to configure based on options\n const doModel = options.quick || options.model || options.all || (!options.channels && !options.gateway);\n const doChannels = !options.quick && (options.channels || options.all || (!options.model && !options.gateway));\n const doGateway = !options.quick && (options.gateway || options.all || (!options.model && !options.channels));\n const runFullWizard = !options.quick && !options.model && !options.channels && !options.gateway;\n /** Any setup step besides the unified launch prompt ran in interactive flow. */\n const didConfigurableSteps = doModel || doChannels || doGateway;\n\n if (!isInteractive()) {\n // Non-interactive mode\n if (doModel) {\n config = await setupNonInteractive(configPath, config);\n }\n if (doChannels) {\n console.log('\\n💬 Channels Configuration (Non-Interactive Mode)\\n');\n console.log('💡 To configure channels, edit the config file manually.');\n }\n if (doGateway) {\n console.log('\\n🌐 Gateway Configuration (Non-Interactive Mode)\\n');\n console.log('💡 To configure gateway, edit the config file manually.');\n }\n } else {\n // Interactive mode\n if (doModel) {\n config = await runModelSetup(config, ctx);\n }\n\n if (doChannels) {\n const channelIds = (await getChannelConfigurators(config)).map(c => c.id);\n console.log(colors.gray(`\\nChannel onboarding: ${channelIds.join(', ')}\\n`));\n config = await runChannelOnboard(config);\n }\n\n if (doGateway) {\n config = await setupGateway(config);\n }\n }\n\n // Save config once at the end\n await saveConfig(config as Config, configPath);\n\n console.log('\\n' + '═'.repeat(50));\n console.log('\\n🎉 Setup Complete!\\n');\n\n const gatewayAuth = (config as any)?.gateway?.auth;\n const gatewayConfigured =\n gatewayAuth?.mode === 'token' &&\n typeof gatewayAuth?.token === 'string' &&\n gatewayAuth.token.length > 0;\n const port = (config as Config)?.gateway?.port ?? 18790;\n const displayHost = resolveGatewayLocalClientHost(config as Config);\n const gwToken = gatewayConfigured ? (gatewayAuth.token as string) : undefined;\n\n const showGatewaySummary = Boolean(gatewayConfigured && gwToken && (doGateway || runFullWizard));\n\n if (showGatewaySummary && gwToken) {\n const webuiUrl = `http://${displayHost}:${port}`;\n console.log('🌐 Web console (browser) — start here');\n console.log(` Open: http://${displayHost}:${port}`);\n console.log(` Token: ${gwToken.slice(0, 8)}...${gwToken.slice(-8)}`);\n console.log(' Open the console and enter the token when prompted:');\n console.log(` ${webuiUrl}`);\n console.log('');\n }\n\n if (runFullWizard) {\n console.log('🚀 Next steps:');\n if (gatewayConfigured) {\n console.log(' 1. Choose how to launch below (gateway or terminal UI)');\n console.log(' 2. Or chat with: xopc agent -i');\n } else {\n console.log(' 1. Chat in the terminal: xopc agent -i');\n console.log(' 2. Optional: add the Web console: xopc onboard --gateway');\n }\n console.log('');\n } else if (doGateway && gatewayConfigured) {\n console.log('🚀 Next step:');\n console.log(' Start the gateway if it is not running, then open the Web console URL above.');\n console.log('');\n }\n\n console.log('📝 Usage:');\n console.log(' xopc agent -m \"Hello\" # Chat with AI');\n console.log(' xopc agent -i # Interactive mode');\n console.log(' xopc models list # List models');\n console.log(' xopc config validate # Validate xopc.json');\n console.log(' xopc auth list # View authentication');\n console.log(' xopc init # Full state dirs (if upgrading or missing data)');\n\n console.log('\\n📁 Files:');\n console.log(' Config:', configPath);\n console.log(' Workspace:', workspacePath);\n\n printGitHubStarHint();\n\n if (isInteractive() && didConfigurableSteps) {\n await promptLaunchAfterOnboard(config as Config, ctx, { doChannels });\n }\n\n process.exit(0);\n}\n\nasync function startGatewayAsService(config: Config, ctx: CLIContext): Promise<void> {\n const { startGatewayNow } = await import('./onboard/gateway.js');\n await startGatewayNow(config, ctx);\n}\n\nasync function promptLaunchAfterOnboard(\n config: Config,\n ctx: CLIContext,\n _flags: { doChannels: boolean },\n): Promise<void> {\n console.log('');\n const choice = await select<'tui' | 'gateway' | 'none'>({\n message: 'How do you want to launch xopc now?',\n choices: [\n {\n value: 'tui',\n name: 'Terminal UI (embedded)',\n description: 'xopc — no gateway process required',\n },\n {\n value: 'gateway',\n name: 'Gateway WebUI (OS service)',\n description: 'Install and start the HTTP gateway for the browser console',\n },\n {\n value: 'none',\n name: 'Exit — I will start manually',\n description: 'Finish setup without starting a runtime',\n },\n ],\n default: 'tui',\n });\n\n if (choice === 'gateway') {\n await startGatewayAsService(config, ctx);\n return;\n }\n\n if (choice === 'tui') {\n const { runTui } = await import('../../tui/tui.js');\n await runTui({ local: true });\n return;\n }\n\n console.log('\\n⏭️ You can start later:');\n console.log(' xopc gateway service install');\n console.log(' xopc gateway');\n console.log(' xopc');\n}\n\nasync function setupGateway(config: Config): Promise<Config> {\n console.log(colors.cyan('\\n🌐 Gateway WebUI\\n'));\n console.log(\n colors.gray(\n 'Applying defaults from config schema (127.0.0.1:18790, token auth; token generated if missing).\\n',\n ),\n );\n\n const gw = config.gateway ?? {};\n const { randomBytes } = await import('node:crypto');\n const authMode = gw.auth?.mode === 'none' ? ('none' as const) : ('token' as const);\n const token =\n authMode === 'token'\n ? typeof gw.auth?.token === 'string' && gw.auth.token.length > 0\n ? gw.auth.token\n : randomBytes(24).toString('hex')\n : undefined;\n\n const merged: Config = {\n ...config,\n gateway: {\n ...gw,\n bind: gw.bind ?? 'loopback',\n port: gw.port ?? 18790,\n auth:\n authMode === 'none'\n ? { mode: 'none' as const }\n : { mode: 'token' as const, token: token! },\n },\n };\n\n const parsed = ConfigSchema.parse(merged);\n console.log('✅ Gateway defaults applied.\\n');\n return parsed;\n}\n\nregister({\n id: 'onboard',\n name: 'onboard',\n description: 'Interactive setup wizard',\n factory: createOnboardCommand,\n metadata: {\n category: 'setup',\n examples: ['xopc onboard', 'xopc onboard --model', 'xopc onboard --channels'],\n },\n});\n"],"mappings":"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"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { init_loader, loadConfig, saveConfig } from "../../config/loader.js";
|
|
2
2
|
import { setTuiDefaultAgentConfig } from "../../commands/agents.config.js";
|
|
3
3
|
import { formatExamples, register } from "../registry.js";
|
|
4
|
+
import { createGatewayCredential } from "../../gateway/credential.js";
|
|
4
5
|
import { detectMigrations, runBootstrapMigrationsSync } from "../../migrations/runner.js";
|
|
5
6
|
import { Command } from "commander";
|
|
6
7
|
//#region src/cli/commands/tui.ts
|
|
@@ -10,12 +11,12 @@ function createTuiCommand(ctx) {
|
|
|
10
11
|
"xopc # Open embedded TUI (default command)",
|
|
11
12
|
"xopc tui # Embedded mode (default)",
|
|
12
13
|
"xopc tui --gateway # Force gateway mode",
|
|
13
|
-
"xopc tui --url http://host:3120 --
|
|
14
|
+
"XOPC_GATEWAY_PASSWORD=xxx xopc tui --url http://host:3120 --password-env XOPC_GATEWAY_PASSWORD",
|
|
14
15
|
"xopc tui -s agent:main:tui-... # Resume a session",
|
|
15
16
|
"xopc tui --agent coder # Start with a specific agent",
|
|
16
17
|
"xopc tui --set-default-agent coder # Persist default agent for new TUI sessions",
|
|
17
18
|
"xopc tui -m \"Summarize my inbox\" # Send a message on launch"
|
|
18
|
-
])).option("--url <url>", "Gateway URL (default: http://localhost:3120)").option("--token <token>", "Gateway bearer token").option("-s, --session <key>", "Session key to resume (omitted: start a fresh TUI session)").option("--agent <id>", "Agent id for a fresh TUI session").option("--set-default-agent <id>", "Persist default agent for new TUI sessions and exit").option("-m, --message <text>", "Send a message on launch").option("--workdir <dir>", "Workspace directory for the new TUI session").option("--no-cwd", "Do not use the launch directory as the new TUI session workspace").option("--local", "Run in embedded mode (no gateway required)").option("--gateway", "Force gateway mode even without explicit
|
|
19
|
+
])).option("--url <url>", "Gateway URL (default: http://localhost:3120)").option("--token <token>", "Gateway bearer token").option("--password-env <name>", "Environment variable holding the gateway password").option("-s, --session <key>", "Session key to resume (omitted: start a fresh TUI session)").option("--agent <id>", "Agent id for a fresh TUI session").option("--set-default-agent <id>", "Persist default agent for new TUI sessions and exit").option("-m, --message <text>", "Send a message on launch").option("--workdir <dir>", "Workspace directory for the new TUI session").option("--no-cwd", "Do not use the launch directory as the new TUI session workspace").option("--local", "Run in embedded mode (no gateway required)").option("--gateway", "Force gateway mode even without an explicit URL or credential").option("--theme <name>", "Theme: auto, dark, light, or custom name from ~/.xopc/themes/").option("--thinking <level>", "Thinking level override").action(async (options) => {
|
|
19
20
|
runBootstrapMigrationsSync(ctx.configPath);
|
|
20
21
|
const pendingMigrations = detectMigrations(ctx.configPath);
|
|
21
22
|
if (pendingMigrations.length > 0) console.warn(`xopc has ${pendingMigrations.length} pending migration(s). Run \`xopc doctor --fix\` or open Settings → App management.`);
|
|
@@ -30,13 +31,19 @@ function createTuiCommand(ctx) {
|
|
|
30
31
|
return;
|
|
31
32
|
}
|
|
32
33
|
const { runTui } = await import("../../tui/tui.js");
|
|
34
|
+
const token = typeof options.token === "string" ? options.token : void 0;
|
|
35
|
+
const passwordEnv = typeof options.passwordEnv === "string" ? options.passwordEnv.trim() : void 0;
|
|
36
|
+
if (token && passwordEnv) throw new Error("Use either --token or --password-env, not both.");
|
|
37
|
+
const password = passwordEnv ? process.env[passwordEnv] : void 0;
|
|
38
|
+
if (passwordEnv && !password) throw new Error(`Gateway password environment variable ${passwordEnv} is not set.`);
|
|
39
|
+
const credential = token ? createGatewayCredential("token", token) : createGatewayCredential("password", password);
|
|
33
40
|
const useLocal = options.local === true;
|
|
34
|
-
const useGateway = options.gateway === true || typeof options.url === "string" ||
|
|
41
|
+
const useGateway = options.gateway === true || typeof options.url === "string" || credential !== void 0;
|
|
35
42
|
if (useLocal && useGateway) console.log("`--local` and gateway flags both set. Using local mode.");
|
|
36
43
|
const localMode = useLocal || !useGateway;
|
|
37
44
|
await runTui({
|
|
38
45
|
url: typeof options.url === "string" ? options.url : void 0,
|
|
39
|
-
|
|
46
|
+
credential,
|
|
40
47
|
session: typeof options.session === "string" ? options.session : void 0,
|
|
41
48
|
agentId: typeof options.agent === "string" ? options.agent : void 0,
|
|
42
49
|
message: typeof options.message === "string" ? options.message : void 0,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tui.js","names":[],"sources":["../../../../src/cli/commands/tui.ts"],"sourcesContent":["import { Command } from 'commander';\n\nimport { setTuiDefaultAgentConfig } from '../../commands/agents.config.js';\nimport { loadConfig, saveConfig } from '../../config/loader.js';\nimport { detectMigrations, runBootstrapMigrationsSync } from '../../migrations/runner.js';\nimport { register, formatExamples, type CLIContext } from '../registry.js';\n\nfunction createTuiCommand(ctx: CLIContext): Command {\n const cmd = new Command('tui')\n .description('Interactive terminal UI (pi-tui)')\n .addHelpText(\n 'after',\n formatExamples([\n 'xopc # Open embedded TUI (default command)',\n 'xopc tui # Embedded mode (default)',\n 'xopc tui --gateway # Force gateway mode',\n 'xopc tui --url http://host:3120 --
|
|
1
|
+
{"version":3,"file":"tui.js","names":[],"sources":["../../../../src/cli/commands/tui.ts"],"sourcesContent":["import { Command } from 'commander';\n\nimport { setTuiDefaultAgentConfig } from '../../commands/agents.config.js';\nimport { loadConfig, saveConfig } from '../../config/loader.js';\nimport { createGatewayCredential } from '../../gateway/credential.js';\nimport { detectMigrations, runBootstrapMigrationsSync } from '../../migrations/runner.js';\nimport { register, formatExamples, type CLIContext } from '../registry.js';\n\nfunction createTuiCommand(ctx: CLIContext): Command {\n const cmd = new Command('tui')\n .description('Interactive terminal UI (pi-tui)')\n .addHelpText(\n 'after',\n formatExamples([\n 'xopc # Open embedded TUI (default command)',\n 'xopc tui # Embedded mode (default)',\n 'xopc tui --gateway # Force gateway mode',\n 'XOPC_GATEWAY_PASSWORD=xxx xopc tui --url http://host:3120 --password-env XOPC_GATEWAY_PASSWORD',\n 'xopc tui -s agent:main:tui-... # Resume a session',\n 'xopc tui --agent coder # Start with a specific agent',\n 'xopc tui --set-default-agent coder # Persist default agent for new TUI sessions',\n 'xopc tui -m \"Summarize my inbox\" # Send a message on launch',\n ]),\n )\n .option('--url <url>', 'Gateway URL (default: http://localhost:3120)')\n .option('--token <token>', 'Gateway bearer token')\n .option('--password-env <name>', 'Environment variable holding the gateway password')\n .option('-s, --session <key>', 'Session key to resume (omitted: start a fresh TUI session)')\n .option('--agent <id>', 'Agent id for a fresh TUI session')\n .option('--set-default-agent <id>', 'Persist default agent for new TUI sessions and exit')\n .option('-m, --message <text>', 'Send a message on launch')\n .option('--workdir <dir>', 'Workspace directory for the new TUI session')\n .option('--no-cwd', 'Do not use the launch directory as the new TUI session workspace')\n .option('--local', 'Run in embedded mode (no gateway required)')\n .option('--gateway', 'Force gateway mode even without an explicit URL or credential')\n .option('--theme <name>', 'Theme: auto, dark, light, or custom name from ~/.xopc/themes/')\n .option('--thinking <level>', 'Thinking level override')\n .action(async (options: Record<string, string | boolean | undefined>) => {\n runBootstrapMigrationsSync(ctx.configPath);\n const pendingMigrations = detectMigrations(ctx.configPath);\n if (pendingMigrations.length > 0) {\n console.warn(\n `xopc has ${pendingMigrations.length} pending migration(s). Run \\`xopc doctor --fix\\` or open Settings → App management.`,\n );\n }\n if (typeof options.setDefaultAgent === 'string') {\n const cfg = loadConfig(ctx.configPath);\n const result = setTuiDefaultAgentConfig(cfg, options.setDefaultAgent);\n if (result.ok === false) {\n console.error(`Error: ${result.message}`);\n process.exit(1);\n }\n await saveConfig(result.config, ctx.configPath);\n console.log(`TUI default agent set to \"${result.agentId}\".`);\n return;\n }\n const { runTui } = await import('../../tui/tui.js');\n const token = typeof options.token === 'string' ? options.token : undefined;\n const passwordEnv = typeof options.passwordEnv === 'string' ? options.passwordEnv.trim() : undefined;\n if (token && passwordEnv) {\n throw new Error('Use either --token or --password-env, not both.');\n }\n const password = passwordEnv ? process.env[passwordEnv] : undefined;\n if (passwordEnv && !password) {\n throw new Error(`Gateway password environment variable ${passwordEnv} is not set.`);\n }\n const credential = token\n ? createGatewayCredential('token', token)\n : createGatewayCredential('password', password);\n const useLocal = options.local === true;\n const useGateway = options.gateway === true || typeof options.url === 'string' || credential !== undefined;\n if (useLocal && useGateway) {\n console.log('`--local` and gateway flags both set. Using local mode.');\n }\n const localMode = useLocal || !useGateway;\n await runTui({\n url: typeof options.url === 'string' ? options.url : undefined,\n credential,\n session: typeof options.session === 'string' ? options.session : undefined,\n agentId: typeof options.agent === 'string' ? options.agent : undefined,\n message: typeof options.message === 'string' ? options.message : undefined,\n workdir: typeof options.workdir === 'string' ? options.workdir : undefined,\n useStartupCwd: options.cwd !== false,\n local: localMode,\n thinking: typeof options.thinking === 'string' ? options.thinking : undefined,\n theme: typeof options.theme === 'string' ? options.theme : undefined,\n });\n });\n\n return cmd;\n}\n\nregister({\n id: 'tui',\n name: 'tui',\n description: 'Interactive terminal UI (pi-tui)',\n factory: createTuiCommand,\n metadata: {\n category: 'runtime',\n examples: [\n 'xopc',\n 'xopc tui',\n 'xopc tui --agent coder',\n 'xopc tui --set-default-agent coder',\n 'xopc tui --gateway',\n 'xopc tui --url http://host:3120',\n ],\n },\n});\n"],"mappings":";;;;;;;aAGgE;AAKhE,SAAS,iBAAiB,KAA0B;AAiFlD,QAhFY,IAAI,QAAQ,MAAM,CAC3B,YAAY,mCAAmC,CAC/C,YACC,SACA,eAAe;EACb;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACD,CAAC,CACH,CACA,OAAO,eAAe,+CAA+C,CACrE,OAAO,mBAAmB,uBAAuB,CACjD,OAAO,yBAAyB,oDAAoD,CACpF,OAAO,uBAAuB,6DAA6D,CAC3F,OAAO,gBAAgB,mCAAmC,CAC1D,OAAO,4BAA4B,sDAAsD,CACzF,OAAO,wBAAwB,2BAA2B,CAC1D,OAAO,mBAAmB,8CAA8C,CACxE,OAAO,YAAY,mEAAmE,CACtF,OAAO,WAAW,6CAA6C,CAC/D,OAAO,aAAa,gEAAgE,CACpF,OAAO,kBAAkB,gEAAgE,CACzF,OAAO,sBAAsB,0BAA0B,CACvD,OAAO,OAAO,YAA0D;AACvE,6BAA2B,IAAI,WAAW;EAC1C,MAAM,oBAAoB,iBAAiB,IAAI,WAAW;AAC1D,MAAI,kBAAkB,SAAS,EAC7B,SAAQ,KACN,YAAY,kBAAkB,OAAO,qFACtC;AAEH,MAAI,OAAO,QAAQ,oBAAoB,UAAU;GAE/C,MAAM,SAAS,yBADH,WAAW,IAAI,WACgB,EAAE,QAAQ,gBAAgB;AACrE,OAAI,OAAO,OAAO,OAAO;AACvB,YAAQ,MAAM,UAAU,OAAO,UAAU;AACzC,YAAQ,KAAK,EAAE;;AAEjB,SAAM,WAAW,OAAO,QAAQ,IAAI,WAAW;AAC/C,WAAQ,IAAI,6BAA6B,OAAO,QAAQ,IAAI;AAC5D;;EAEF,MAAM,EAAE,WAAW,MAAM,OAAO;EAChC,MAAM,QAAQ,OAAO,QAAQ,UAAU,WAAW,QAAQ,QAAQ,KAAA;EAClE,MAAM,cAAc,OAAO,QAAQ,gBAAgB,WAAW,QAAQ,YAAY,MAAM,GAAG,KAAA;AAC3F,MAAI,SAAS,YACX,OAAM,IAAI,MAAM,kDAAkD;EAEpE,MAAM,WAAW,cAAc,QAAQ,IAAI,eAAe,KAAA;AAC1D,MAAI,eAAe,CAAC,SAClB,OAAM,IAAI,MAAM,yCAAyC,YAAY,cAAc;EAErF,MAAM,aAAa,QACf,wBAAwB,SAAS,MAAM,GACvC,wBAAwB,YAAY,SAAS;EACjD,MAAM,WAAW,QAAQ,UAAU;EACnC,MAAM,aAAa,QAAQ,YAAY,QAAQ,OAAO,QAAQ,QAAQ,YAAY,eAAe,KAAA;AACjG,MAAI,YAAY,WACd,SAAQ,IAAI,0DAA0D;EAExE,MAAM,YAAY,YAAY,CAAC;AAC/B,QAAM,OAAO;GACX,KAAK,OAAO,QAAQ,QAAQ,WAAW,QAAQ,MAAM,KAAA;GACrD;GACA,SAAS,OAAO,QAAQ,YAAY,WAAW,QAAQ,UAAU,KAAA;GACjE,SAAS,OAAO,QAAQ,UAAU,WAAW,QAAQ,QAAQ,KAAA;GAC7D,SAAS,OAAO,QAAQ,YAAY,WAAW,QAAQ,UAAU,KAAA;GACjE,SAAS,OAAO,QAAQ,YAAY,WAAW,QAAQ,UAAU,KAAA;GACjE,eAAe,QAAQ,QAAQ;GAC/B,OAAO;GACP,UAAU,OAAO,QAAQ,aAAa,WAAW,QAAQ,WAAW,KAAA;GACpE,OAAO,OAAO,QAAQ,UAAU,WAAW,QAAQ,QAAQ,KAAA;GAC5D,CAAC;GAGI;;AAGZ,SAAS;CACP,IAAI;CACJ,MAAM;CACN,aAAa;CACb,SAAS;CACT,UAAU;EACR,UAAU;EACV,UAAU;GACR;GACA;GACA;GACA;GACA;GACA;GACD;EACF;CACF,CAAC"}
|
|
@@ -7,9 +7,12 @@
|
|
|
7
7
|
* helpers in `gateway-client.ts` are dynamically imported inside actions.
|
|
8
8
|
*/
|
|
9
9
|
import type { Command } from 'commander';
|
|
10
|
+
import type { GatewayCredential } from '../../gateway/credential.js';
|
|
10
11
|
export interface GatewayClientOptions {
|
|
11
12
|
url?: string;
|
|
12
13
|
token?: string;
|
|
14
|
+
passwordEnv?: string;
|
|
15
|
+
credential?: GatewayCredential;
|
|
13
16
|
timeoutMs?: number;
|
|
14
17
|
json?: boolean;
|
|
15
18
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
//#region src/cli/utils/gateway-client-options.ts
|
|
2
2
|
function addGatewayClientOptions(cmd) {
|
|
3
|
-
return cmd.option("--url <url>", "Gateway HTTP URL (defaults to config or http://127.0.0.1:18790)").option("--token <token>", "Gateway auth token").option("--timeout <ms>", "Request timeout in ms", "10000").option("--json", "Output raw JSON", false);
|
|
3
|
+
return cmd.option("--url <url>", "Gateway HTTP URL (defaults to config or http://127.0.0.1:18790)").option("--token <token>", "Gateway auth token").option("--password-env <name>", "Environment variable holding the gateway password").option("--timeout <ms>", "Request timeout in ms", "10000").option("--json", "Output raw JSON", false);
|
|
4
4
|
}
|
|
5
5
|
function parseGatewayClientOptions(opts) {
|
|
6
6
|
const rawTimeout = opts.timeout;
|
|
@@ -8,6 +8,7 @@ function parseGatewayClientOptions(opts) {
|
|
|
8
8
|
return {
|
|
9
9
|
url: typeof opts.url === "string" ? opts.url : void 0,
|
|
10
10
|
token: typeof opts.token === "string" ? opts.token : void 0,
|
|
11
|
+
passwordEnv: typeof opts.passwordEnv === "string" ? opts.passwordEnv : void 0,
|
|
11
12
|
timeoutMs,
|
|
12
13
|
json: Boolean(opts.json)
|
|
13
14
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gateway-client-options.js","names":[],"sources":["../../../../src/cli/utils/gateway-client-options.ts"],"sourcesContent":["/**\n * Lightweight option helpers for gateway CLI subcommands.\n *\n * Kept separate from `gateway-client.ts` so subcommand files can statically\n * import these (called at command construction time) without dragging in\n * `loadConfig` / `createLogger` and their transitive graph. The heavy HTTP\n * helpers in `gateway-client.ts` are dynamically imported inside actions.\n */\nimport type { Command } from 'commander';\n\nexport interface GatewayClientOptions {\n url?: string;\n token?: string;\n timeoutMs?: number;\n json?: boolean;\n}\n\nexport function addGatewayClientOptions(cmd: Command): Command {\n return cmd\n .option('--url <url>', 'Gateway HTTP URL (defaults to config or http://127.0.0.1:18790)')\n .option('--token <token>', 'Gateway auth token')\n .option('--timeout <ms>', 'Request timeout in ms', '10000')\n .option('--json', 'Output raw JSON', false);\n}\n\nexport function parseGatewayClientOptions(opts: Record<string, unknown>): GatewayClientOptions {\n const rawTimeout = opts.timeout;\n const timeoutMs =\n typeof rawTimeout === 'string'\n ? Number.parseInt(rawTimeout, 10) || 10_000\n : typeof rawTimeout === 'number' && Number.isFinite(rawTimeout)\n ? rawTimeout\n : 10_000;\n return {\n url: typeof opts.url === 'string' ? opts.url : undefined,\n token: typeof opts.token === 'string' ? opts.token : undefined,\n timeoutMs,\n json: Boolean(opts.json),\n };\n}\n"],"mappings":";
|
|
1
|
+
{"version":3,"file":"gateway-client-options.js","names":[],"sources":["../../../../src/cli/utils/gateway-client-options.ts"],"sourcesContent":["/**\n * Lightweight option helpers for gateway CLI subcommands.\n *\n * Kept separate from `gateway-client.ts` so subcommand files can statically\n * import these (called at command construction time) without dragging in\n * `loadConfig` / `createLogger` and their transitive graph. The heavy HTTP\n * helpers in `gateway-client.ts` are dynamically imported inside actions.\n */\nimport type { Command } from 'commander';\nimport type { GatewayCredential } from '../../gateway/credential.js';\n\nexport interface GatewayClientOptions {\n url?: string;\n token?: string;\n passwordEnv?: string;\n credential?: GatewayCredential;\n timeoutMs?: number;\n json?: boolean;\n}\n\nexport function addGatewayClientOptions(cmd: Command): Command {\n return cmd\n .option('--url <url>', 'Gateway HTTP URL (defaults to config or http://127.0.0.1:18790)')\n .option('--token <token>', 'Gateway auth token')\n .option('--password-env <name>', 'Environment variable holding the gateway password')\n .option('--timeout <ms>', 'Request timeout in ms', '10000')\n .option('--json', 'Output raw JSON', false);\n}\n\nexport function parseGatewayClientOptions(opts: Record<string, unknown>): GatewayClientOptions {\n const rawTimeout = opts.timeout;\n const timeoutMs =\n typeof rawTimeout === 'string'\n ? Number.parseInt(rawTimeout, 10) || 10_000\n : typeof rawTimeout === 'number' && Number.isFinite(rawTimeout)\n ? rawTimeout\n : 10_000;\n return {\n url: typeof opts.url === 'string' ? opts.url : undefined,\n token: typeof opts.token === 'string' ? opts.token : undefined,\n passwordEnv: typeof opts.passwordEnv === 'string' ? opts.passwordEnv : undefined,\n timeoutMs,\n json: Boolean(opts.json),\n };\n}\n"],"mappings":";AAoBA,SAAgB,wBAAwB,KAAuB;AAC7D,QAAO,IACJ,OAAO,eAAe,kEAAkE,CACxF,OAAO,mBAAmB,qBAAqB,CAC/C,OAAO,yBAAyB,oDAAoD,CACpF,OAAO,kBAAkB,yBAAyB,QAAQ,CAC1D,OAAO,UAAU,mBAAmB,MAAM;;AAG/C,SAAgB,0BAA0B,MAAqD;CAC7F,MAAM,aAAa,KAAK;CACxB,MAAM,YACJ,OAAO,eAAe,WAClB,OAAO,SAAS,YAAY,GAAG,IAAI,MACnC,OAAO,eAAe,YAAY,OAAO,SAAS,WAAW,GAC3D,aACA;AACR,QAAO;EACL,KAAK,OAAO,KAAK,QAAQ,WAAW,KAAK,MAAM,KAAA;EAC/C,OAAO,OAAO,KAAK,UAAU,WAAW,KAAK,QAAQ,KAAA;EACrD,aAAa,OAAO,KAAK,gBAAgB,WAAW,KAAK,cAAc,KAAA;EACvE;EACA,MAAM,QAAQ,KAAK,KAAK;EACzB"}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Gateway API client — CLI-side HTTP client for gateway REST routes.
|
|
3
3
|
*/
|
|
4
|
+
import { type GatewayCredential } from '../../gateway/credential.js';
|
|
4
5
|
import type { GatewayClientOptions } from './gateway-client-options.js';
|
|
5
6
|
export type { GatewayClientOptions } from './gateway-client-options.js';
|
|
6
|
-
export { addGatewayClientOptions, parseGatewayClientOptions
|
|
7
|
+
export { addGatewayClientOptions, parseGatewayClientOptions } from './gateway-client-options.js';
|
|
7
8
|
export interface GatewayCallResult<T = unknown> {
|
|
8
9
|
ok: boolean;
|
|
9
10
|
status: number;
|
|
@@ -15,8 +16,10 @@ export declare function resolveGatewayUrl(opts?: {
|
|
|
15
16
|
url?: string;
|
|
16
17
|
configPath?: string;
|
|
17
18
|
}): string;
|
|
18
|
-
export declare function
|
|
19
|
+
export declare function resolveGatewayCredential(opts?: {
|
|
19
20
|
token?: string;
|
|
21
|
+
passwordEnv?: string;
|
|
22
|
+
credential?: GatewayCredential;
|
|
20
23
|
configPath?: string;
|
|
21
|
-
}):
|
|
24
|
+
}): GatewayCredential | undefined;
|
|
22
25
|
export declare function callGatewayApi<T = unknown>(method: 'GET' | 'POST' | 'PATCH' | 'DELETE', path: string, opts?: GatewayClientOptions, body?: unknown): Promise<GatewayCallResult<T>>;
|
|
@@ -4,6 +4,7 @@ import { init_paths, resolveConfigPath } from "../../config/paths.js";
|
|
|
4
4
|
import { loadConfig } from "../../config/loader.js";
|
|
5
5
|
import { resolveGatewayEffectiveHost } from "../../config/gateway-bind.js";
|
|
6
6
|
import "../../config/index.js";
|
|
7
|
+
import { createGatewayCredential, gatewayCredentialAuthorization } from "../../gateway/credential.js";
|
|
7
8
|
import { assertSecureGatewayHttpUrl } from "../../gateway/ws-security.js";
|
|
8
9
|
import { addGatewayClientOptions, parseGatewayClientOptions } from "./gateway-client-options.js";
|
|
9
10
|
//#region src/cli/utils/gateway-client.ts
|
|
@@ -41,28 +42,33 @@ function resolveGatewayUrl(opts) {
|
|
|
41
42
|
return "http://127.0.0.1:18790";
|
|
42
43
|
}
|
|
43
44
|
}
|
|
44
|
-
function
|
|
45
|
-
if (opts?.
|
|
45
|
+
function resolveGatewayCredential(opts) {
|
|
46
|
+
if (opts?.credential) return opts.credential;
|
|
47
|
+
if (opts?.token && opts.passwordEnv) throw new Error("Use either --token or --password-env, not both.");
|
|
48
|
+
if (opts?.token) return createGatewayCredential("token", opts.token);
|
|
49
|
+
if (opts?.passwordEnv) return createGatewayCredential("password", process.env[opts.passwordEnv]);
|
|
46
50
|
const envToken = process.env.XOPC_GATEWAY_TOKEN;
|
|
47
|
-
if (envToken) return envToken;
|
|
51
|
+
if (envToken) return createGatewayCredential("token", envToken);
|
|
48
52
|
try {
|
|
49
53
|
const config = loadConfig(opts?.configPath ?? resolveConfigPath());
|
|
50
54
|
if (config.gateway?.mode === "remote") {
|
|
51
55
|
const remoteToken = config.gateway.remote?.token?.trim();
|
|
52
|
-
if (remoteToken) return remoteToken;
|
|
56
|
+
if (remoteToken) return createGatewayCredential("token", remoteToken);
|
|
53
57
|
}
|
|
54
|
-
|
|
58
|
+
const auth = config.gateway?.auth;
|
|
59
|
+
return auth?.mode === "password" ? createGatewayCredential("password", auth.password) : createGatewayCredential("token", auth?.token);
|
|
55
60
|
} catch {
|
|
56
61
|
return;
|
|
57
62
|
}
|
|
58
63
|
}
|
|
59
64
|
async function callGatewayApi(method, path, opts, body) {
|
|
60
65
|
const baseUrl = resolveGatewayUrl(opts);
|
|
61
|
-
const
|
|
66
|
+
const credential = resolveGatewayCredential(opts);
|
|
62
67
|
const timeoutMs = opts?.timeoutMs ?? 1e4;
|
|
63
68
|
const url = `${baseUrl}${path.startsWith("/") ? path : `/${path}`}`;
|
|
64
69
|
const headers = { Accept: "application/json" };
|
|
65
|
-
|
|
70
|
+
const authorization = gatewayCredentialAuthorization(credential);
|
|
71
|
+
if (authorization) headers.Authorization = authorization;
|
|
66
72
|
if (body !== void 0) headers["Content-Type"] = "application/json";
|
|
67
73
|
const startedAt = Date.now();
|
|
68
74
|
try {
|
|
@@ -125,6 +131,6 @@ async function callGatewayApi(method, path, opts, body) {
|
|
|
125
131
|
}
|
|
126
132
|
}
|
|
127
133
|
//#endregion
|
|
128
|
-
export { addGatewayClientOptions, callGatewayApi, parseGatewayClientOptions,
|
|
134
|
+
export { addGatewayClientOptions, callGatewayApi, parseGatewayClientOptions, resolveGatewayCredential, resolveGatewayUrl };
|
|
129
135
|
|
|
130
136
|
//# sourceMappingURL=gateway-client.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gateway-client.js","names":[],"sources":["../../../../src/cli/utils/gateway-client.ts"],"sourcesContent":["/**\n * Gateway API client — CLI-side HTTP client for gateway REST routes.\n */\n\nimport { loadConfig } from '../../config/index.js';\nimport { resolveConfigPath } from '../../config/paths.js';\nimport { resolveGatewayEffectiveHost } from '../../config/gateway-bind.js';\nimport { assertSecureGatewayHttpUrl } from '../../gateway/ws-security.js';\nimport { createLogger } from '../../utils/logger.js';\nimport type { GatewayClientOptions } from './gateway-client-options.js';\n\nexport type { GatewayClientOptions } from './gateway-client-options.js';\nexport {
|
|
1
|
+
{"version":3,"file":"gateway-client.js","names":[],"sources":["../../../../src/cli/utils/gateway-client.ts"],"sourcesContent":["/**\n * Gateway API client — CLI-side HTTP client for gateway REST routes.\n */\n\nimport { loadConfig } from '../../config/index.js';\nimport { resolveConfigPath } from '../../config/paths.js';\nimport { resolveGatewayEffectiveHost } from '../../config/gateway-bind.js';\nimport { assertSecureGatewayHttpUrl } from '../../gateway/ws-security.js';\nimport {\n createGatewayCredential,\n gatewayCredentialAuthorization,\n type GatewayCredential,\n} from '../../gateway/credential.js';\nimport { createLogger } from '../../utils/logger.js';\nimport type { GatewayClientOptions } from './gateway-client-options.js';\n\nexport type { GatewayClientOptions } from './gateway-client-options.js';\nexport { addGatewayClientOptions, parseGatewayClientOptions } from './gateway-client-options.js';\n\nconst log = createLogger('GatewayClient');\n\nexport interface GatewayCallResult<T = unknown> {\n ok: boolean;\n status: number;\n data?: T;\n error?: string;\n durationMs: number;\n}\n\nexport function resolveGatewayUrl(opts?: { url?: string; configPath?: string }): string {\n if (opts?.url) {\n const normalized = opts.url.replace(/\\/+$/, '');\n assertSecureGatewayHttpUrl(normalized);\n return normalized;\n }\n\n const envUrl = process.env.XOPC_GATEWAY_URL?.trim();\n if (envUrl) {\n const normalized = envUrl.replace(/\\/+$/, '');\n assertSecureGatewayHttpUrl(normalized);\n return normalized;\n }\n\n try {\n const configPath = opts?.configPath ?? resolveConfigPath();\n const config = loadConfig(configPath);\n if (config.gateway?.mode === 'remote' && config.gateway.remote?.url?.trim()) {\n const normalized = config.gateway.remote.url.trim().replace(/\\/+$/, '');\n assertSecureGatewayHttpUrl(normalized);\n return normalized;\n }\n const host = resolveGatewayEffectiveHost(config);\n const port = config?.gateway?.port ?? 18790;\n const displayHost = host === '0.0.0.0' ? '127.0.0.1' : host;\n const url = `http://${displayHost}:${port}`;\n assertSecureGatewayHttpUrl(url);\n return url;\n } catch {\n return 'http://127.0.0.1:18790';\n }\n}\n\nexport function resolveGatewayCredential(opts?: {\n token?: string;\n passwordEnv?: string;\n credential?: GatewayCredential;\n configPath?: string;\n}): GatewayCredential | undefined {\n if (opts?.credential) return opts.credential;\n if (opts?.token && opts.passwordEnv) {\n throw new Error('Use either --token or --password-env, not both.');\n }\n if (opts?.token) return createGatewayCredential('token', opts.token);\n if (opts?.passwordEnv) {\n return createGatewayCredential('password', process.env[opts.passwordEnv]);\n }\n\n const envToken = process.env.XOPC_GATEWAY_TOKEN;\n if (envToken) return createGatewayCredential('token', envToken);\n\n try {\n const configPath = opts?.configPath ?? resolveConfigPath();\n const config = loadConfig(configPath);\n if (config.gateway?.mode === 'remote') {\n const remoteToken = config.gateway.remote?.token?.trim();\n if (remoteToken) return createGatewayCredential('token', remoteToken);\n }\n const auth = config.gateway?.auth;\n return auth?.mode === 'password'\n ? createGatewayCredential('password', auth.password)\n : createGatewayCredential('token', auth?.token);\n } catch {\n return undefined;\n }\n}\n\nexport async function callGatewayApi<T = unknown>(\n method: 'GET' | 'POST' | 'PATCH' | 'DELETE',\n path: string,\n opts?: GatewayClientOptions,\n body?: unknown,\n): Promise<GatewayCallResult<T>> {\n const baseUrl = resolveGatewayUrl(opts);\n const credential = resolveGatewayCredential(opts);\n const timeoutMs = opts?.timeoutMs ?? 10_000;\n const url = `${baseUrl}${path.startsWith('/') ? path : `/${path}`}`;\n\n const headers: Record<string, string> = {\n Accept: 'application/json',\n };\n const authorization = gatewayCredentialAuthorization(credential);\n if (authorization) {\n headers.Authorization = authorization;\n }\n if (body !== undefined) {\n headers['Content-Type'] = 'application/json';\n }\n\n const startedAt = Date.now();\n\n try {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), timeoutMs);\n\n const response = await fetch(url, {\n method,\n headers,\n body: body !== undefined ? JSON.stringify(body) : undefined,\n signal: controller.signal,\n });\n\n clearTimeout(timer);\n const durationMs = Date.now() - startedAt;\n\n if (!response.ok) {\n let errorMessage: string;\n try {\n const errorBody = (await response.json()) as {\n error?: string;\n message?: string;\n };\n errorMessage = errorBody.error || errorBody.message || response.statusText;\n } catch {\n errorMessage = response.statusText;\n }\n\n log.debug({ url, status: response.status, durationMs }, `Gateway call failed: ${errorMessage}`);\n return {\n ok: false,\n status: response.status,\n error: errorMessage,\n durationMs,\n };\n }\n\n const data = (await response.json()) as T;\n log.debug({ url, status: response.status, durationMs }, 'Gateway call succeeded');\n return { ok: true, status: response.status, data, durationMs };\n } catch (err) {\n const durationMs = Date.now() - startedAt;\n const isAbort = err instanceof Error && err.name === 'AbortError';\n const errorMessage = isAbort\n ? `Request timed out after ${timeoutMs}ms`\n : err instanceof Error\n ? err.message\n : String(err);\n\n log.debug({ url, err, durationMs }, `Gateway call error: ${errorMessage}`);\n return { ok: false, status: 0, error: errorMessage, durationMs };\n }\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export type GatewayCredential = {
|
|
2
|
+
kind: 'token';
|
|
3
|
+
value: string;
|
|
4
|
+
} | {
|
|
5
|
+
kind: 'password';
|
|
6
|
+
value: string;
|
|
7
|
+
};
|
|
8
|
+
export declare function createGatewayCredential(kind: GatewayCredential['kind'], value: string | undefined): GatewayCredential | undefined;
|
|
9
|
+
export declare function gatewayCredentialAuthorization(credential: GatewayCredential | undefined): string | undefined;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
//#region src/gateway/credential.ts
|
|
2
|
+
function createGatewayCredential(kind, value) {
|
|
3
|
+
const trimmed = value?.trim();
|
|
4
|
+
return trimmed ? {
|
|
5
|
+
kind,
|
|
6
|
+
value: trimmed
|
|
7
|
+
} : void 0;
|
|
8
|
+
}
|
|
9
|
+
function gatewayCredentialAuthorization(credential) {
|
|
10
|
+
if (!credential || /[\r\n]/.test(credential.value)) return void 0;
|
|
11
|
+
return `Bearer ${credential.value}`;
|
|
12
|
+
}
|
|
13
|
+
//#endregion
|
|
14
|
+
export { createGatewayCredential, gatewayCredentialAuthorization };
|
|
15
|
+
|
|
16
|
+
//# sourceMappingURL=credential.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"credential.js","names":[],"sources":["../../../src/gateway/credential.ts"],"sourcesContent":["export type GatewayCredential = { kind: 'token'; value: string } | { kind: 'password'; value: string };\n\nexport function createGatewayCredential(\n kind: GatewayCredential['kind'],\n value: string | undefined,\n): GatewayCredential | undefined {\n const trimmed = value?.trim();\n return trimmed ? { kind, value: trimmed } : undefined;\n}\n\nexport function gatewayCredentialAuthorization(credential: GatewayCredential | undefined): string | undefined {\n if (!credential || /[\\r\\n]/.test(credential.value)) return undefined;\n return `Bearer ${credential.value}`;\n}\n"],"mappings":";AAEA,SAAgB,wBACd,MACA,OAC+B;CAC/B,MAAM,UAAU,OAAO,MAAM;AAC7B,QAAO,UAAU;EAAE;EAAM,OAAO;EAAS,GAAG,KAAA;;AAG9C,SAAgB,+BAA+B,YAA+D;AAC5G,KAAI,CAAC,cAAc,SAAS,KAAK,WAAW,MAAM,CAAE,QAAO,KAAA;AAC3D,QAAO,UAAU,WAAW"}
|
|
@@ -40,7 +40,7 @@ function isExtensionGatewayUiAssetPath(path) {
|
|
|
40
40
|
}
|
|
41
41
|
function createHonoApp(config) {
|
|
42
42
|
if (process.env.VITEST) resetLazyRouteBundlesForTests();
|
|
43
|
-
const { service
|
|
43
|
+
const { service } = config;
|
|
44
44
|
const app = new Hono();
|
|
45
45
|
const gatewayPort = resolveGatewayServiceListenPort(service);
|
|
46
46
|
const resolveBrowserOrigins = () => resolveAllowedBrowserOrigins({
|
|
@@ -194,15 +194,8 @@ function createHonoApp(config) {
|
|
|
194
194
|
const authenticated = new Hono();
|
|
195
195
|
authenticated.use(routeErrorMiddleware());
|
|
196
196
|
authenticated.use(auth({
|
|
197
|
-
token,
|
|
198
197
|
getGatewayAuth: () => service.currentConfig.gateway?.auth,
|
|
199
|
-
getResolvedAuth: () =>
|
|
200
|
-
if (typeof service.getResolvedAuth === "function") return service.getResolvedAuth();
|
|
201
|
-
return token ? {
|
|
202
|
-
mode: "token",
|
|
203
|
-
token
|
|
204
|
-
} : { mode: "none" };
|
|
205
|
-
},
|
|
198
|
+
getResolvedAuth: () => service.getResolvedAuth(),
|
|
206
199
|
getTrustedProxyContext: () => ({
|
|
207
200
|
trustedProxies: service.currentConfig.gateway?.trustedProxies,
|
|
208
201
|
allowRealIpFallback: service.currentConfig.gateway?.allowRealIpFallback === true
|