@visiblebase/manager 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (98) hide show
  1. package/README.md +33 -0
  2. package/bin/admin/auth-error.d.ts +30 -0
  3. package/bin/admin/auth-error.d.ts.map +1 -0
  4. package/bin/admin/auth-error.js +45 -0
  5. package/bin/admin/auth-error.js.map +1 -0
  6. package/bin/admin/commands/accounts.d.ts +6 -0
  7. package/bin/admin/commands/accounts.d.ts.map +1 -0
  8. package/bin/admin/commands/accounts.js +44 -0
  9. package/bin/admin/commands/accounts.js.map +1 -0
  10. package/bin/admin/commands/balance.d.ts +6 -0
  11. package/bin/admin/commands/balance.d.ts.map +1 -0
  12. package/bin/admin/commands/balance.js +100 -0
  13. package/bin/admin/commands/balance.js.map +1 -0
  14. package/bin/admin/commands/config.d.ts +9 -0
  15. package/bin/admin/commands/config.d.ts.map +1 -0
  16. package/bin/admin/commands/config.js +55 -0
  17. package/bin/admin/commands/config.js.map +1 -0
  18. package/bin/admin/commands/custom.d.ts +6 -0
  19. package/bin/admin/commands/custom.d.ts.map +1 -0
  20. package/bin/admin/commands/custom.js +47 -0
  21. package/bin/admin/commands/custom.js.map +1 -0
  22. package/bin/admin/commands/models.d.ts +14 -0
  23. package/bin/admin/commands/models.d.ts.map +1 -0
  24. package/bin/admin/commands/models.js +56 -0
  25. package/bin/admin/commands/models.js.map +1 -0
  26. package/bin/admin/commands/payment.d.ts +6 -0
  27. package/bin/admin/commands/payment.d.ts.map +1 -0
  28. package/bin/admin/commands/payment.js +33 -0
  29. package/bin/admin/commands/payment.js.map +1 -0
  30. package/bin/admin/commands/plugin-env.d.ts +11 -0
  31. package/bin/admin/commands/plugin-env.d.ts.map +1 -0
  32. package/bin/admin/commands/plugin-env.js +283 -0
  33. package/bin/admin/commands/plugin-env.js.map +1 -0
  34. package/bin/admin/commands/products.d.ts +6 -0
  35. package/bin/admin/commands/products.d.ts.map +1 -0
  36. package/bin/admin/commands/products.js +77 -0
  37. package/bin/admin/commands/products.js.map +1 -0
  38. package/bin/admin/commands/usage.d.ts +6 -0
  39. package/bin/admin/commands/usage.d.ts.map +1 -0
  40. package/bin/admin/commands/usage.js +44 -0
  41. package/bin/admin/commands/usage.js.map +1 -0
  42. package/bin/admin/loop.d.ts +6 -0
  43. package/bin/admin/loop.d.ts.map +1 -0
  44. package/bin/admin/loop.js +75 -0
  45. package/bin/admin/loop.js.map +1 -0
  46. package/bin/agent/pi-agent.d.ts +15 -0
  47. package/bin/agent/pi-agent.d.ts.map +1 -0
  48. package/bin/agent/pi-agent.js +136 -0
  49. package/bin/agent/pi-agent.js.map +1 -0
  50. package/bin/app.d.ts +13 -0
  51. package/bin/app.d.ts.map +1 -0
  52. package/bin/app.js +67 -0
  53. package/bin/app.js.map +1 -0
  54. package/bin/auth/admin.d.ts +8 -0
  55. package/bin/auth/admin.d.ts.map +1 -0
  56. package/bin/auth/admin.js +24 -0
  57. package/bin/auth/admin.js.map +1 -0
  58. package/bin/auth/mode-select.d.ts +12 -0
  59. package/bin/auth/mode-select.d.ts.map +1 -0
  60. package/bin/auth/mode-select.js +30 -0
  61. package/bin/auth/mode-select.js.map +1 -0
  62. package/bin/auth/server-switch.d.ts +16 -0
  63. package/bin/auth/server-switch.d.ts.map +1 -0
  64. package/bin/auth/server-switch.js +98 -0
  65. package/bin/auth/server-switch.js.map +1 -0
  66. package/bin/auth/user.d.ts +21 -0
  67. package/bin/auth/user.d.ts.map +1 -0
  68. package/bin/auth/user.js +223 -0
  69. package/bin/auth/user.js.map +1 -0
  70. package/bin/core/env.d.ts +15 -0
  71. package/bin/core/env.d.ts.map +1 -0
  72. package/bin/core/env.js +67 -0
  73. package/bin/core/env.js.map +1 -0
  74. package/bin/core/session.d.ts +53 -0
  75. package/bin/core/session.d.ts.map +1 -0
  76. package/bin/core/session.js +118 -0
  77. package/bin/core/session.js.map +1 -0
  78. package/bin/core/ui.d.ts +29 -0
  79. package/bin/core/ui.d.ts.map +1 -0
  80. package/bin/core/ui.js +58 -0
  81. package/bin/core/ui.js.map +1 -0
  82. package/bin/user/balance.d.ts +19 -0
  83. package/bin/user/balance.d.ts.map +1 -0
  84. package/bin/user/balance.js +62 -0
  85. package/bin/user/balance.js.map +1 -0
  86. package/bin/user/chat.d.ts +12 -0
  87. package/bin/user/chat.d.ts.map +1 -0
  88. package/bin/user/chat.js +70 -0
  89. package/bin/user/chat.js.map +1 -0
  90. package/bin/user/loop.d.ts +13 -0
  91. package/bin/user/loop.d.ts.map +1 -0
  92. package/bin/user/loop.js +87 -0
  93. package/bin/user/loop.js.map +1 -0
  94. package/bin/user/models.d.ts +10 -0
  95. package/bin/user/models.d.ts.map +1 -0
  96. package/bin/user/models.js +39 -0
  97. package/bin/user/models.js.map +1 -0
  98. package/package.json +52 -0
@@ -0,0 +1,223 @@
1
+ /**
2
+ * User 鉴权模块。
3
+ *
4
+ * 支持四种登录方式:
5
+ * 1. Email Login — 邮箱 + 密码直接登录
6
+ * 2. Email Register — 邮箱 + 密码注册 → 验证码 → 完成
7
+ * 3. GitHub OAuth — 浏览器授权
8
+ * 4. Google OAuth — 浏览器授权
9
+ *
10
+ * 已有有效 session 直接返回,不重复鉴权。
11
+ */
12
+ import { execSync } from "node:child_process";
13
+ import { UserClient } from "@visiblebase/client";
14
+ import { select, isCancel } from "@clack/prompts";
15
+ import { normalizeBaseUrl } from "../core/env.js";
16
+ import { readUserSession, writeUserSession, readConfig } from "../core/session.js";
17
+ import { askText, askSecret, showError, showSuccess, show } from "../core/ui.js";
18
+ // ===========================================================================
19
+ // 入口
20
+ // ===========================================================================
21
+ export async function userAuth(baseUrl) {
22
+ const existing = readUserSession(normalizeBaseUrl(baseUrl));
23
+ if (existing)
24
+ return { session: existing, config: readConfig() };
25
+ while (true) {
26
+ const method = await selectAuthMethod();
27
+ if (!method)
28
+ return undefined;
29
+ const ctx = await doAuth(baseUrl, method);
30
+ if (ctx)
31
+ return ctx;
32
+ }
33
+ }
34
+ async function selectAuthMethod() {
35
+ const selected = await select({
36
+ message: "Sign in",
37
+ options: [
38
+ { label: "Email Login", value: "login", hint: "Sign in with email + password" },
39
+ { label: "Email Register", value: "register", hint: "Create a new account" },
40
+ { label: "GitHub", value: "github", hint: "Sign in with GitHub OAuth" },
41
+ { label: "Google", value: "google", hint: "Sign in with Google OAuth" },
42
+ ],
43
+ });
44
+ if (!selected || isCancel(selected))
45
+ return undefined;
46
+ return selected;
47
+ }
48
+ // ===========================================================================
49
+ // 鉴权分发
50
+ // ===========================================================================
51
+ async function doAuth(baseUrl, method) {
52
+ switch (method) {
53
+ case "login": return emailLogin(baseUrl);
54
+ case "register": return emailRegister(baseUrl);
55
+ case "github": return oauthAuth(baseUrl, "github");
56
+ case "google": return oauthAuth(baseUrl, "google");
57
+ }
58
+ }
59
+ async function emailLogin(baseUrl) {
60
+ const email = await askText("email");
61
+ if (!email || !email.includes("@")) {
62
+ showError("invalid email");
63
+ return undefined;
64
+ }
65
+ const password = await askSecret("password");
66
+ if (!password)
67
+ return undefined;
68
+ const client = new UserClient({ base_url: normalizeBaseUrl(baseUrl) });
69
+ const accounts = client.service("accounts");
70
+ try {
71
+ const result = await accounts.action("login").invoke({ email, password });
72
+ if (result.error) {
73
+ showError(result.error);
74
+ return undefined;
75
+ }
76
+ if (!result.user_token) {
77
+ showError("login failed: no token");
78
+ return undefined;
79
+ }
80
+ return saveSession(baseUrl, email, result);
81
+ }
82
+ catch (e) {
83
+ showError(e instanceof Error ? e.message : String(e));
84
+ return undefined;
85
+ }
86
+ }
87
+ async function emailRegister(baseUrl) {
88
+ const email = await askText("email");
89
+ if (!email || !email.includes("@")) {
90
+ showError("invalid email");
91
+ return undefined;
92
+ }
93
+ const password = await askSecret("password (min 8 characters)");
94
+ if (!password || password.length < 8) {
95
+ showError("password must be at least 8 characters");
96
+ return undefined;
97
+ }
98
+ const client = new UserClient({ base_url: normalizeBaseUrl(baseUrl) });
99
+ const accounts = client.service("accounts");
100
+ let reg;
101
+ try {
102
+ reg = await accounts.action("register").invoke({ email, password });
103
+ }
104
+ catch (e) {
105
+ showError(e instanceof Error ? e.message : String(e));
106
+ return undefined;
107
+ }
108
+ if (reg.error) {
109
+ showError(reg.error);
110
+ return undefined;
111
+ }
112
+ if (!reg.success) {
113
+ showError("registration failed");
114
+ return undefined;
115
+ }
116
+ showSuccess("Verification code sent to your email");
117
+ show("If email delivery is unavailable, check server logs for the verification code.");
118
+ const token = await askText("verification token");
119
+ if (!token)
120
+ return undefined;
121
+ try {
122
+ const verify = await accounts.action("verify-email").invoke({ token: token.trim() });
123
+ if (verify.error) {
124
+ showError(verify.error);
125
+ return undefined;
126
+ }
127
+ if (!verify.user_token) {
128
+ showError("verification failed: no token");
129
+ return undefined;
130
+ }
131
+ return saveSession(baseUrl, email, verify);
132
+ }
133
+ catch (e) {
134
+ showError(e instanceof Error ? e.message : String(e));
135
+ return undefined;
136
+ }
137
+ }
138
+ async function oauthAuth(baseUrl, provider) {
139
+ const client = new UserClient({ base_url: normalizeBaseUrl(baseUrl) });
140
+ const accounts = client.service("accounts");
141
+ let start;
142
+ try {
143
+ start = await accounts.action("oauth/start").invoke({ provider });
144
+ }
145
+ catch (e) {
146
+ showError(e instanceof Error ? e.message : String(e));
147
+ return undefined;
148
+ }
149
+ if (start.error) {
150
+ showError(start.error);
151
+ return undefined;
152
+ }
153
+ if (!start.url || !start.state) {
154
+ showError("failed to start OAuth");
155
+ return undefined;
156
+ }
157
+ show(`Opening browser for ${provider} authorization...`);
158
+ const opened = openBrowser(start.url);
159
+ if (!opened)
160
+ showError(`Could not open browser. Please visit:\n ${start.url}`);
161
+ show("Waiting for authorization...");
162
+ const result = await pollOAuth(client, start.state);
163
+ if (!result || result.error) {
164
+ showError(result?.error ?? "OAuth failed");
165
+ return undefined;
166
+ }
167
+ if (!result.user_token) {
168
+ showError("OAuth failed: no token");
169
+ return undefined;
170
+ }
171
+ showSuccess(`${provider} login successful`);
172
+ return saveSession(baseUrl, `${provider}:`, result);
173
+ }
174
+ /** 轮询 OAuth 结果(最多 3 分钟) */
175
+ async function pollOAuth(client, state) {
176
+ const accounts = client.service("accounts");
177
+ for (let i = 0; i < 180; i++) {
178
+ try {
179
+ const result = await accounts.get("oauth/result", { state });
180
+ if (result.error)
181
+ return result;
182
+ if (result.status === "done")
183
+ return result;
184
+ }
185
+ catch { /* continue polling */ }
186
+ await sleep(1000);
187
+ }
188
+ return { error: "OAuth timed out" };
189
+ }
190
+ // ===========================================================================
191
+ // 工具函数
192
+ // ===========================================================================
193
+ function saveSession(baseUrl, email, result) {
194
+ const session = {
195
+ base_url: normalizeBaseUrl(baseUrl),
196
+ email,
197
+ user_id: result.user_id ?? "",
198
+ product_id: "prod_visiblebase",
199
+ user_token: result.user_token,
200
+ };
201
+ writeUserSession(session);
202
+ showSuccess(`signed in: ${email}`);
203
+ return { session, config: readConfig() };
204
+ }
205
+ /** 打开系统默认浏览器 */
206
+ function openBrowser(url) {
207
+ try {
208
+ if (process.platform === "darwin")
209
+ execSync(`open "${url}"`);
210
+ else if (process.platform === "win32")
211
+ execSync(`start "" "${url}"`);
212
+ else
213
+ execSync(`xdg-open "${url}"`);
214
+ return true;
215
+ }
216
+ catch {
217
+ return false;
218
+ }
219
+ }
220
+ function sleep(ms) {
221
+ return new Promise((resolve) => setTimeout(resolve, ms));
222
+ }
223
+ //# sourceMappingURL=user.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"user.js","sourceRoot":"","sources":["../../src/auth/user.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * 运行时工具模块。
3
+ *
4
+ * 提供 CLI 参数解析、URL 规范化等基础设施。
5
+ */
6
+ export declare const DEFAULT_HOST = "127.0.0.1";
7
+ export declare const DEFAULT_PORT = 43127;
8
+ export declare const DEFAULT_BASE_URL = "http://127.0.0.1:43127";
9
+ export declare const DEFAULT_PRODUCT_ID = "prod_visiblebase";
10
+ export declare function parseArgs(argv: string[]): {
11
+ command: string;
12
+ options: Record<string, string | boolean>;
13
+ };
14
+ export declare function normalizeBaseUrl(baseUrl?: string): string;
15
+ //# sourceMappingURL=env.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../../src/core/env.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAMH,eAAO,MAAM,YAAY,cAAc,CAAC;AACxC,eAAO,MAAM,YAAY,QAAQ,CAAC;AAClC,eAAO,MAAM,gBAAgB,2BAA2C,CAAC;AACzE,eAAO,MAAM,kBAAkB,qBAAqB,CAAC;AAMrD,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE;;;EAevC;AAMD,wBAAgB,gBAAgB,CAAC,OAAO,SAAmB,GAAG,MAAM,CAWnE"}
@@ -0,0 +1,67 @@
1
+ /**
2
+ * 运行时工具模块。
3
+ *
4
+ * 提供 CLI 参数解析、URL 规范化等基础设施。
5
+ */
6
+ // ============================================================
7
+ // 常量
8
+ // ============================================================
9
+ export const DEFAULT_HOST = "127.0.0.1";
10
+ export const DEFAULT_PORT = 43127;
11
+ export const DEFAULT_BASE_URL = `http://${DEFAULT_HOST}:${DEFAULT_PORT}`;
12
+ export const DEFAULT_PRODUCT_ID = "prod_visiblebase";
13
+ // ============================================================
14
+ // CLI 参数解析
15
+ // ============================================================
16
+ export function parseArgs(argv) {
17
+ const positionals = [];
18
+ const options = {};
19
+ for (let index = 0; index < argv.length; index += 1) {
20
+ const token = argv[index];
21
+ if (!token.startsWith("--")) {
22
+ positionals.push(token);
23
+ continue;
24
+ }
25
+ const key = token.slice(2).replace(/-([a-z])/g, (_, l) => l.toUpperCase());
26
+ const next = argv[index + 1];
27
+ if (!next || next.startsWith("--")) {
28
+ options[key] = true;
29
+ continue;
30
+ }
31
+ options[key] = next;
32
+ index += 1;
33
+ }
34
+ return { command: positionals[0] ?? "", options };
35
+ }
36
+ // ============================================================
37
+ // URL 规范化
38
+ // ============================================================
39
+ export function normalizeBaseUrl(baseUrl = DEFAULT_BASE_URL) {
40
+ const raw = String(baseUrl).trim();
41
+ if (!raw)
42
+ return DEFAULT_BASE_URL;
43
+ const hasProtocol = /^[a-z][a-z\d+.-]*:\/\//iu.test(raw);
44
+ const withProtocol = hasProtocol ? raw : `${defaultProtocol(raw)}://${raw}`;
45
+ const url = new URL(withProtocol);
46
+ if (!url.port && isLocalOrIp(url.hostname))
47
+ url.port = String(DEFAULT_PORT);
48
+ if (!url.pathname || url.pathname === "/")
49
+ url.pathname = "/";
50
+ return url.toString().replace(/\/+$/, "");
51
+ }
52
+ // ============================================================
53
+ // 内部辅助
54
+ // ============================================================
55
+ function defaultProtocol(value) {
56
+ const host = value.split("/")[0] ?? "";
57
+ return (isLocalOrIp(host.split(":")[0] ?? "") || host.includes(":")) ? "http" : "https";
58
+ }
59
+ function isLocalOrIp(value) {
60
+ const host = value.replace(/^\[/u, "").replace(/\]$/u, "");
61
+ return host === "localhost" || isIpv4Host(host) || host.includes(":");
62
+ }
63
+ function isIpv4Host(value) {
64
+ const parts = value.split(".");
65
+ return parts.length === 4 && parts.every((p) => /^\d+$/u.test(p) && Number(p) <= 255);
66
+ }
67
+ //# sourceMappingURL=env.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env.js","sourceRoot":"","sources":["../../src/core/env.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Session 持久化模块。
3
+ *
4
+ * 支持多服务端地址,每个地址独立保存 admin / user session。
5
+ * 使用 URL 哈希作为目录名,避免特殊字符问题。
6
+ */
7
+ export interface AdminSession {
8
+ base_url: string;
9
+ admin_token: string;
10
+ }
11
+ export interface UserSession {
12
+ base_url: string;
13
+ email: string;
14
+ user_id: string;
15
+ product_id: string;
16
+ user_token: string;
17
+ }
18
+ /** 单个服务端配置 */
19
+ export interface ServerProfile {
20
+ /** 显示名称 */
21
+ name: string;
22
+ /** 服务端 URL */
23
+ url: string;
24
+ }
25
+ export interface ClientConfig {
26
+ /** 当前激活的服务端 URL */
27
+ base_url: string;
28
+ /** 已保存的服务端列表 */
29
+ servers: ServerProfile[];
30
+ /** 当前选择的模型 ID */
31
+ model: string;
32
+ /** 上次使用的身份 */
33
+ last_identity?: "admin" | "user";
34
+ }
35
+ /** 从磁盘读取 config,缺失字段用默认值补齐 */
36
+ export declare function readConfig(): ClientConfig;
37
+ /** 写入 config 到磁盘 */
38
+ export declare function writeConfig(c: ClientConfig): void;
39
+ /** 切换激活的服务端(caller 保证 url 已在 servers 列表中) */
40
+ export declare function switchServer(url: string): void;
41
+ /** 添加服务端(同名则更新名称) */
42
+ export declare function addServer(name: string, url: string): void;
43
+ /** 删除服务端,同时清除其 session */
44
+ export declare function removeServer(url: string): void;
45
+ export declare function readAdminSession(url: string): AdminSession | undefined;
46
+ export declare function writeAdminSession(s: AdminSession): void;
47
+ export declare function clearAdminSession(url: string): void;
48
+ export declare function readUserSession(url: string): UserSession | undefined;
49
+ export declare function writeUserSession(s: UserSession): void;
50
+ export declare function clearUserSession(url: string): void;
51
+ /** 清除某服务端的所有 session(admin + user) */
52
+ export declare function clearServerSessions(url: string): void;
53
+ //# sourceMappingURL=session.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../src/core/session.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAcH,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,cAAc;AACd,MAAM,WAAW,aAAa;IAC5B,WAAW;IACX,IAAI,EAAE,MAAM,CAAC;IACb,cAAc;IACd,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,YAAY;IAC3B,mBAAmB;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,gBAAgB;IAChB,OAAO,EAAE,aAAa,EAAE,CAAC;IACzB,iBAAiB;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,cAAc;IACd,aAAa,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;CAClC;AAMD,8BAA8B;AAC9B,wBAAgB,UAAU,IAAI,YAAY,CAWzC;AAED,oBAAoB;AACpB,wBAAgB,WAAW,CAAC,CAAC,EAAE,YAAY,GAAG,IAAI,CAEjD;AAMD,6CAA6C;AAC7C,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAI9C;AAED,qBAAqB;AACrB,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,CAMzD;AAED,0BAA0B;AAC1B,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAQ9C;AAaD,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS,CAEtE;AAED,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,YAAY,GAAG,IAAI,CAEvD;AAED,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAEnD;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS,CAEpE;AAED,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,WAAW,GAAG,IAAI,CAErD;AAED,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAElD;AAED,sCAAsC;AACtC,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAGrD"}
@@ -0,0 +1,118 @@
1
+ /**
2
+ * Session 持久化模块。
3
+ *
4
+ * 支持多服务端地址,每个地址独立保存 admin / user session。
5
+ * 使用 URL 哈希作为目录名,避免特殊字符问题。
6
+ */
7
+ import fs from "node:fs";
8
+ import path from "node:path";
9
+ import crypto from "node:crypto";
10
+ import { DEFAULT_BASE_URL } from "./env.js";
11
+ const DIR = path.join(process.cwd(), ".viba");
12
+ const CONFIG_FILE = path.join(DIR, "config.json");
13
+ // ============================================================
14
+ // Config 读写
15
+ // ============================================================
16
+ /** 从磁盘读取 config,缺失字段用默认值补齐 */
17
+ export function readConfig() {
18
+ const c = readJSON(CONFIG_FILE) ?? {};
19
+ const servers = c.servers ?? [];
20
+ const base_url = c.base_url ?? servers[0]?.url ?? DEFAULT_BASE_URL;
21
+ // 确保当前 base_url 在 servers 列表中
22
+ if (servers.length === 0 || !servers.find((s) => s.url === base_url)) {
23
+ servers.unshift({ name: "default", url: base_url });
24
+ }
25
+ return { base_url, servers, model: c.model ?? "", last_identity: c.last_identity };
26
+ }
27
+ /** 写入 config 到磁盘 */
28
+ export function writeConfig(c) {
29
+ writeJSON(CONFIG_FILE, c);
30
+ }
31
+ // ============================================================
32
+ // 服务端管理
33
+ // ============================================================
34
+ /** 切换激活的服务端(caller 保证 url 已在 servers 列表中) */
35
+ export function switchServer(url) {
36
+ const config = readConfig();
37
+ config.base_url = url;
38
+ writeConfig(config);
39
+ }
40
+ /** 添加服务端(同名则更新名称) */
41
+ export function addServer(name, url) {
42
+ const config = readConfig();
43
+ const normalized = url.replace(/\/+$/, "");
44
+ const existing = config.servers.find((s) => s.url === normalized);
45
+ if (existing) {
46
+ existing.name = name;
47
+ }
48
+ else {
49
+ config.servers.push({ name, url: normalized });
50
+ }
51
+ writeConfig(config);
52
+ }
53
+ /** 删除服务端,同时清除其 session */
54
+ export function removeServer(url) {
55
+ const config = readConfig();
56
+ config.servers = config.servers.filter((s) => s.url !== url);
57
+ if (config.base_url === url) {
58
+ config.base_url = config.servers[0]?.url ?? DEFAULT_BASE_URL;
59
+ }
60
+ writeConfig(config);
61
+ clearServerSessions(url);
62
+ }
63
+ // ============================================================
64
+ // Session 读写(按 URL 隔离)
65
+ // ============================================================
66
+ function sessionDir(url) {
67
+ return path.join(DIR, "servers", urlHash(url));
68
+ }
69
+ function adminFile(url) { return path.join(sessionDir(url), "admin.json"); }
70
+ function userFile(url) { return path.join(sessionDir(url), "user.json"); }
71
+ export function readAdminSession(url) {
72
+ return readJSON(adminFile(url));
73
+ }
74
+ export function writeAdminSession(s) {
75
+ writeJSON(adminFile(s.base_url), s);
76
+ }
77
+ export function clearAdminSession(url) {
78
+ try {
79
+ fs.unlinkSync(adminFile(url));
80
+ }
81
+ catch { /* ok */ }
82
+ }
83
+ export function readUserSession(url) {
84
+ return readJSON(userFile(url));
85
+ }
86
+ export function writeUserSession(s) {
87
+ writeJSON(userFile(s.base_url), s);
88
+ }
89
+ export function clearUserSession(url) {
90
+ try {
91
+ fs.unlinkSync(userFile(url));
92
+ }
93
+ catch { /* ok */ }
94
+ }
95
+ /** 清除某服务端的所有 session(admin + user) */
96
+ export function clearServerSessions(url) {
97
+ clearAdminSession(url);
98
+ clearUserSession(url);
99
+ }
100
+ // ============================================================
101
+ // 内部工具
102
+ // ============================================================
103
+ function urlHash(url) {
104
+ return crypto.createHash("sha256").update(url).digest("hex").slice(0, 16);
105
+ }
106
+ function readJSON(filepath) {
107
+ try {
108
+ return JSON.parse(fs.readFileSync(filepath, "utf8"));
109
+ }
110
+ catch {
111
+ return undefined;
112
+ }
113
+ }
114
+ function writeJSON(filepath, data) {
115
+ fs.mkdirSync(path.dirname(filepath), { recursive: true });
116
+ fs.writeFileSync(filepath, JSON.stringify(data, null, 2));
117
+ }
118
+ //# sourceMappingURL=session.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.js","sourceRoot":"","sources":["../../src/core/session.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * UI 工具模块。
3
+ *
4
+ * 提供 CLI 交互所需的输入/输出封装。
5
+ * 模型选择接受通用的 { id, name, hint } 数组,不依赖 server model 类型。
6
+ */
7
+ import { isCancel, intro, log } from "@clack/prompts";
8
+ export { intro, log, isCancel };
9
+ export declare function show(text: string): void;
10
+ export declare function showError(text: string): void;
11
+ export declare function showSuccess(text: string): void;
12
+ /** 主命令菜单 */
13
+ export declare function askUserCommand(): Promise<string | undefined>;
14
+ /** 文本输入 */
15
+ export declare function askText(label: string): Promise<string | undefined>;
16
+ /** 密码输入 */
17
+ export declare function askSecret(label: string): Promise<string | undefined>;
18
+ /** 模型选项 */
19
+ export interface ModelOption {
20
+ /** 模型 ID */
21
+ id: string;
22
+ /** 模型展示名 */
23
+ name: string;
24
+ /** 提示信息 */
25
+ hint: string;
26
+ }
27
+ /** 列出并选择模型,返回模型 id 或 undefined */
28
+ export declare function askModel(models: ModelOption[], currentModel: string): Promise<string | undefined>;
29
+ //# sourceMappingURL=ui.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ui.d.ts","sourceRoot":"","sources":["../../src/core/ui.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAA0B,QAAQ,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,gBAAgB,CAAC;AAE9E,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,QAAQ,EAAE,CAAC;AAMhC,wBAAgB,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAoB;AAC5D,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAqB;AAClE,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAuB;AAMtE,YAAY;AACZ,wBAAsB,cAAc,IAAI,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAiBlE;AAED,WAAW;AACX,wBAAsB,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAGxE;AAED,WAAW;AACX,wBAAsB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAG1E;AAMD,WAAW;AACX,MAAM,WAAW,WAAW;IAC1B,YAAY;IACZ,EAAE,EAAE,MAAM,CAAC;IACX,YAAY;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,WAAW;IACX,IAAI,EAAE,MAAM,CAAC;CACd;AAED,kCAAkC;AAClC,wBAAsB,QAAQ,CAC5B,MAAM,EAAE,WAAW,EAAE,EACrB,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAQ7B"}
package/bin/core/ui.js ADDED
@@ -0,0 +1,58 @@
1
+ /**
2
+ * UI 工具模块。
3
+ *
4
+ * 提供 CLI 交互所需的输入/输出封装。
5
+ * 模型选择接受通用的 { id, name, hint } 数组,不依赖 server model 类型。
6
+ */
7
+ import { password, select, text, isCancel, intro, log } from "@clack/prompts";
8
+ export { intro, log, isCancel };
9
+ // ============================================================
10
+ // 显示函数
11
+ // ============================================================
12
+ export function show(text) { log.info(text); }
13
+ export function showError(text) { log.error(text); }
14
+ export function showSuccess(text) { log.success(text); }
15
+ // ============================================================
16
+ // 交互 prompts
17
+ // ============================================================
18
+ /** 主命令菜单 */
19
+ export async function askUserCommand() {
20
+ const s = await select({ message: "Command", options: [
21
+ { label: "Chat (agent)", value: "chat", hint: "Continuous conversation with pi-agent" },
22
+ { label: "Models", value: "models", hint: "List and select model" },
23
+ { label: "Balance", value: "balance", hint: "View current balance" },
24
+ { label: "History", value: "history", hint: "View balance ledger" },
25
+ { label: "Topups", value: "topups", hint: "View recharge orders" },
26
+ { label: "Recharge", value: "recharge", hint: "Create a topup order" },
27
+ { label: "My profile", value: "me" },
28
+ { label: "List services", value: "services" },
29
+ { label: "Call service", value: "service" },
30
+ { label: "Switch to Admin", value: "switch" },
31
+ { label: "Logout", value: "logout" },
32
+ { label: "Quit", value: "quit" },
33
+ ] });
34
+ if (!s || isCancel(s))
35
+ return undefined;
36
+ return s;
37
+ }
38
+ /** 文本输入 */
39
+ export async function askText(label) {
40
+ const v = await text({ message: label });
41
+ return (!v || isCancel(v)) ? undefined : v;
42
+ }
43
+ /** 密码输入 */
44
+ export async function askSecret(label) {
45
+ const v = await password({ message: label });
46
+ return (!v || isCancel(v)) ? undefined : v;
47
+ }
48
+ /** 列出并选择模型,返回模型 id 或 undefined */
49
+ export async function askModel(models, currentModel) {
50
+ const options = models.map((m) => ({
51
+ label: m.id === currentModel ? `★ ${m.name}` : ` ${m.name}`,
52
+ value: m.id,
53
+ hint: m.hint,
54
+ }));
55
+ const s = await select({ message: "Select model (★ current)", options });
56
+ return (!s || isCancel(s)) ? undefined : String(s);
57
+ }
58
+ //# sourceMappingURL=ui.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ui.js","sourceRoot":"","sources":["../../src/core/ui.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * User Balance 命令。
3
+ *
4
+ * 提供:
5
+ * - 查看当前余额
6
+ * - 查看个人流水
7
+ * - 查看个人充值单
8
+ * - 发起充值
9
+ */
10
+ import type { UserClient } from "@visiblebase/client";
11
+ /** 展示当前余额 */
12
+ export declare function showBalance(c: UserClient): Promise<void>;
13
+ /** 展示个人流水 */
14
+ export declare function showBalanceHistory(c: UserClient): Promise<void>;
15
+ /** 展示个人充值单 */
16
+ export declare function showTopups(c: UserClient): Promise<void>;
17
+ /** 发起充值 */
18
+ export declare function createTopup(c: UserClient): Promise<void>;
19
+ //# sourceMappingURL=balance.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"balance.d.ts","sourceRoot":"","sources":["../../src/user/balance.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAwCtD,aAAa;AACb,wBAAsB,WAAW,CAAC,CAAC,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAM9D;AAED,aAAa;AACb,wBAAsB,kBAAkB,CAAC,CAAC,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAYrE;AAED,cAAc;AACd,wBAAsB,UAAU,CAAC,CAAC,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAY7D;AAED,WAAW;AACX,wBAAsB,WAAW,CAAC,CAAC,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAgB9D"}