downcity 1.1.126 → 1.1.127

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "downcity",
3
- "version": "1.1.126",
3
+ "version": "1.1.127",
4
4
  "type": "module",
5
5
  "description": "Downcity CLI bundle — installs city and town commands",
6
6
  "bin": {
@@ -45,8 +45,8 @@
45
45
  "ws": "^8.21.0",
46
46
  "zod": "^4.4.3",
47
47
  "@downcity/agent": "^1.1.100",
48
- "@downcity/city": "^0.2.56",
49
- "@downcity/plugins": "^1.0.51"
48
+ "@downcity/plugins": "^1.0.51",
49
+ "@downcity/city": "^0.2.56"
50
50
  },
51
51
  "scripts": {
52
52
  "build": "node scripts/copy-cli-products.mjs && node scripts/ensure-cli-executable.mjs",
@@ -1 +1 @@
1
- {"version":3,"file":"CityCommand.d.ts","sourceRoot":"","sources":["../../src/command/CityCommand.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAczC;;GAEG;AACH,wBAAgB,6BAA6B,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAkFpE"}
1
+ {"version":3,"file":"CityCommand.d.ts","sourceRoot":"","sources":["../../src/command/CityCommand.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAezC;;GAEG;AACH,wBAAgB,6BAA6B,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA0FpE"}
@@ -7,7 +7,8 @@
7
7
  * - `city` CLI 只负责 admin/base 管理,`town city` 只负责 user login。
8
8
  */
9
9
  import { parseBoolean } from "../shared/IndexSupport.js";
10
- import { DEFAULT_TOWN_ID, emitCityConnectionStatus, emitCityServerList, runCityConnectCommand, runCityDisconnectCommand, runCityLoginCommand, runCityLogoutCommand, runCityUseCommand, runInteractiveCityManager, } from "../shared/CityConnection.js";
10
+ import { DEFAULT_TOWN_ID } from "../shared/CityStateStore.js";
11
+ import { emitCityConnectionStatus, emitCityUserWhoami, emitCityServerList, runCityConnectCommand, runCityDisconnectCommand, runCityLoginCommand, runCityLogoutCommand, runCityUseCommand, runInteractiveCityManager, } from "../shared/CityConnection.js";
11
12
  /**
12
13
  * 注册 `town city` 命令组。
13
14
  */
@@ -37,6 +38,13 @@ export function registerCityConnectionCommand(program) {
37
38
  .action((options) => {
38
39
  emitCityServerList({ as_json: options.json === true });
39
40
  });
41
+ city
42
+ .command("whoami")
43
+ .description("查看 Town 当前实际使用的 City user")
44
+ .option("--json [enabled]", "以 JSON 输出", parseBoolean)
45
+ .action(async (options) => {
46
+ await emitCityUserWhoami({ as_json: options.json === true });
47
+ });
40
48
  city
41
49
  .command("connect [url]")
42
50
  .description("手动添加并选择一个 City base(默认 base.downcity.ai)")
@@ -1 +1 @@
1
- {"version":3,"file":"CityCommand.js","sourceRoot":"","sources":["../../src/command/CityCommand.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"CityCommand.js","sourceRoot":"","sources":["../../src/command/CityCommand.ts"],"names":[],"mappings":"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"}
@@ -7,19 +7,18 @@
7
7
  * - 交互菜单只调用这里的高层函数,避免 CityConnection 模块继续膨胀。
8
8
  */
9
9
  import type { TownCityBalanceAccount, TownCityRechargeInput, TownCityRechargeResult } from "../types/TownCityBalance.js";
10
- import type { TownCityUserSession } from "../types/TownCitySession.js";
11
10
  /**
12
11
  * 读取当前 Town City user 的余额。
13
12
  */
14
- export declare function readCurrentTownCityBalance(session: TownCityUserSession | null): Promise<TownCityBalanceAccount | null>;
13
+ export declare function readCurrentTownCityBalance(): Promise<TownCityBalanceAccount>;
15
14
  /**
16
15
  * 给当前 Town City user 发起充值。
17
16
  */
18
- export declare function rechargeCurrentTownCityUser(session: TownCityUserSession | null, input: TownCityRechargeInput): Promise<TownCityRechargeResult | null>;
17
+ export declare function rechargeCurrentTownCityUser(input: TownCityRechargeInput): Promise<TownCityRechargeResult>;
19
18
  /**
20
19
  * 输出当前 user 余额。
21
20
  */
22
- export declare function emitCurrentTownCityBalance(session: TownCityUserSession | null): Promise<void>;
21
+ export declare function emitCurrentTownCityBalance(): Promise<void>;
23
22
  /**
24
23
  * 输出当前 user 充值结果。
25
24
  */
@@ -1 +1 @@
1
- {"version":3,"file":"CityBalance.d.ts","sourceRoot":"","sources":["../../src/shared/CityBalance.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAKH,OAAO,KAAK,EACV,sBAAsB,EAGtB,qBAAqB,EACrB,sBAAsB,EACvB,MAAM,6BAA6B,CAAC;AACrC,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AAgBvE;;GAEG;AACH,wBAAsB,0BAA0B,CAC9C,OAAO,EAAE,mBAAmB,GAAG,IAAI,GAClC,OAAO,CAAC,sBAAsB,GAAG,IAAI,CAAC,CAQxC;AAED;;GAEG;AACH,wBAAsB,2BAA2B,CAC/C,OAAO,EAAE,mBAAmB,GAAG,IAAI,EACnC,KAAK,EAAE,qBAAqB,GAC3B,OAAO,CAAC,sBAAsB,GAAG,IAAI,CAAC,CA8BxC;AAwCD;;GAEG;AACH,wBAAsB,0BAA0B,CAC9C,OAAO,EAAE,mBAAmB,GAAG,IAAI,GAClC,OAAO,CAAC,IAAI,CAAC,CAef;AAED;;GAEG;AACH,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,sBAAsB,GAAG,IAAI,CAoB/E"}
1
+ {"version":3,"file":"CityBalance.d.ts","sourceRoot":"","sources":["../../src/shared/CityBalance.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAKH,OAAO,KAAK,EACV,sBAAsB,EAGtB,qBAAqB,EACrB,sBAAsB,EACvB,MAAM,6BAA6B,CAAC;AAKrC;;GAEG;AACH,wBAAsB,0BAA0B,IAAI,OAAO,CAAC,sBAAsB,CAAC,CAKlF;AAED;;GAEG;AACH,wBAAsB,2BAA2B,CAC/C,KAAK,EAAE,qBAAqB,GAC3B,OAAO,CAAC,sBAAsB,CAAC,CA0BjC;AAmBD;;GAEG;AACH,wBAAsB,0BAA0B,IAAI,OAAO,CAAC,IAAI,CAAC,CAchE;AAED;;GAEG;AACH,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,sBAAsB,GAAG,IAAI,CAoB/E"}
@@ -7,31 +7,24 @@
7
7
  * - 交互菜单只调用这里的高层函数,避免 CityConnection 模块继续膨胀。
8
8
  */
9
9
  import { spawnSync } from "node:child_process";
10
- import { City } from "@downcity/city";
11
10
  import { emitCliBlock } from "./CliReporter.js";
11
+ import { CityUserManager } from "./CityUserManager.js";
12
12
  const DEFAULT_PAYMENT_METHOD_ID = "stripe";
13
+ const cityUserManager = new CityUserManager();
13
14
  /**
14
15
  * 读取当前 Town City user 的余额。
15
16
  */
16
- export async function readCurrentTownCityBalance(session) {
17
- const client = createCurrentUserCityClient(session);
18
- if (!client)
19
- return null;
20
- const current_user_id = await readCurrentTokenUserId(client);
21
- assertSessionUserMatchesToken(session, current_user_id);
17
+ export async function readCurrentTownCityBalance() {
18
+ const { user, client } = await cityUserManager.createUserClient();
22
19
  const account = await client.service("balance").get("me");
23
- assertBalanceUserMatchesToken(account, current_user_id);
20
+ assertBalanceUserMatchesToken(account, user.user_id);
24
21
  return account;
25
22
  }
26
23
  /**
27
24
  * 给当前 Town City user 发起充值。
28
25
  */
29
- export async function rechargeCurrentTownCityUser(session, input) {
30
- const client = createCurrentUserCityClient(session);
31
- if (!client)
32
- return null;
33
- const current_user_id = await readCurrentTokenUserId(client);
34
- assertSessionUserMatchesToken(session, current_user_id);
26
+ export async function rechargeCurrentTownCityUser(input) {
27
+ const { client } = await cityUserManager.createUserClient();
35
28
  const amount = normalizePositiveInteger(input.amount, "amount");
36
29
  const method_id = normalizeText(input.method_id) || DEFAULT_PAYMENT_METHOD_ID;
37
30
  const topup = await client.service("balance").action("topups/create").invoke({
@@ -56,26 +49,10 @@ export async function rechargeCurrentTownCityUser(session, input) {
56
49
  opened,
57
50
  };
58
51
  }
59
- async function readCurrentTokenUserId(client) {
60
- const result = await client.service("accounts").get("me");
61
- const user_id = normalizeText(result.user?.user_id);
62
- if (!user_id) {
63
- throw new Error("City user token resolved without a user_id. Please run `town city login` again.");
64
- }
65
- return user_id;
66
- }
67
- function assertSessionUserMatchesToken(session, token_user_id) {
68
- const session_user_id = normalizeText(session?.user_id);
69
- if (session_user_id && session_user_id !== token_user_id) {
70
- throw new Error([
71
- "Town City session user does not match the authenticated token.",
72
- `session=${session_user_id}`,
73
- `token=${token_user_id}`,
74
- "Run `town city logout` and then `town city login`.",
75
- ].join(" "));
76
- }
77
- }
78
52
  function assertBalanceUserMatchesToken(account, token_user_id) {
53
+ if (!token_user_id) {
54
+ throw new Error("City user token resolved without a user_id. Run `town city login` again.");
55
+ }
79
56
  if (account.user_id !== token_user_id) {
80
57
  throw new Error([
81
58
  "Balance account user does not match the authenticated token.",
@@ -88,10 +65,8 @@ function assertBalanceUserMatchesToken(account, token_user_id) {
88
65
  /**
89
66
  * 输出当前 user 余额。
90
67
  */
91
- export async function emitCurrentTownCityBalance(session) {
92
- const account = await readCurrentTownCityBalance(session);
93
- if (!account)
94
- return;
68
+ export async function emitCurrentTownCityBalance() {
69
+ const account = await readCurrentTownCityBalance();
95
70
  emitCliBlock({
96
71
  tone: "success",
97
72
  title: "User balance",
@@ -128,22 +103,6 @@ export function emitTownCityRechargeResult(result) {
128
103
  : "Checkout URL was not returned by the payment service.",
129
104
  });
130
105
  }
131
- function createCurrentUserCityClient(session) {
132
- if (!session) {
133
- emitCliBlock({
134
- tone: "warning",
135
- title: "City user not signed in",
136
- note: "Run `town city login` first, or choose User 登录 in this manager.",
137
- });
138
- return null;
139
- }
140
- return new City({
141
- role: "user",
142
- city_url: session.base_url,
143
- town_id: session.town_id,
144
- user_token: session.user_token,
145
- });
146
- }
147
106
  function normalizePositiveInteger(value, label) {
148
107
  const amount = typeof value === "number" ? value : Number(value);
149
108
  if (!Number.isInteger(amount) || amount <= 0) {
@@ -1 +1 @@
1
- {"version":3,"file":"CityBalance.js","sourceRoot":"","sources":["../../src/shared/CityBalance.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"CityBalance.js","sourceRoot":"","sources":["../../src/shared/CityBalance.ts"],"names":[],"mappings":"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"}
@@ -8,21 +8,14 @@
8
8
  * - CLI 命令装配统一放在 `src/command/CityCommand.ts`,本模块只保留状态与登录流程。
9
9
  */
10
10
  import type { TownCityConnectionState } from "../types/TownCityConnection.js";
11
- import type { TownCityUserSession } from "../types/TownCitySession.js";
12
- export declare const DEFAULT_CITY_URL = "https://base.downcity.ai";
13
- export declare const DEFAULT_TOWN_ID = "town_downcity";
14
- export declare function normalizeCityUrl(value: string): string;
15
11
  export declare function readTownCityAdminSecretForBase(city_url: string): string | undefined;
16
- export declare function readCurrentTownCitySession(): TownCityUserSession | null;
17
- export declare function readTownCityUserSessionForRuntime(): {
18
- city_url: string;
19
- town_id: string;
20
- user_token: string;
21
- } | null;
22
12
  export declare function readTownCityConnectionState(): TownCityConnectionState;
23
13
  export declare function emitCityConnectionStatus(options?: {
24
14
  as_json?: boolean;
25
15
  }): void;
16
+ export declare function emitCityUserWhoami(options?: {
17
+ as_json?: boolean;
18
+ }): Promise<void>;
26
19
  export declare function emitCityServerList(options?: {
27
20
  as_json?: boolean;
28
21
  }): void;
@@ -1 +1 @@
1
- {"version":3,"file":"CityConnection.d.ts","sourceRoot":"","sources":["../../src/shared/CityConnection.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAeH,OAAO,KAAK,EACV,uBAAuB,EAExB,MAAM,gCAAgC,CAAC;AACxC,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AAOvE,eAAO,MAAM,gBAAgB,6BAA6B,CAAC;AAC3D,eAAO,MAAM,eAAe,kBAAkB,CAAC;AAqB/C,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAatD;AAsHD,wBAAgB,8BAA8B,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAEnF;AAkGD,wBAAgB,0BAA0B,IAAI,mBAAmB,GAAG,IAAI,CAIvE;AAED,wBAAgB,iCAAiC,IAAI;IACnD,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;CACpB,GAAG,IAAI,CAUP;AAED,wBAAgB,2BAA2B,IAAI,uBAAuB,CA0BrE;AAED,wBAAgB,wBAAwB,CAAC,OAAO,CAAC,EAAE;IAAE,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,IAAI,CA8B9E;AAED,wBAAgB,kBAAkB,CAAC,OAAO,CAAC,EAAE;IAAE,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,IAAI,CA+BxE;AAED,wBAAsB,qBAAqB,CAAC,MAAM,EAAE;IAClD,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,GAAG,OAAO,CAAC,IAAI,CAAC,CA2BhB;AAED,wBAAsB,iBAAiB,CAAC,MAAM,EAAE;IAC9C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,GAAG,OAAO,CAAC,IAAI,CAAC,CAgChB;AAiBD,wBAAsB,mBAAmB,CAAC,MAAM,EAAE;IAChD,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,GAAG,OAAO,CAAC,IAAI,CAAC,CAoChB;AAED,wBAAgB,oBAAoB,CAAC,OAAO,CAAC,EAAE;IAAE,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,IAAI,CAiB1E;AAED,wBAAgB,wBAAwB,CAAC,OAAO,CAAC,EAAE;IAAE,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,IAAI,CAqB9E;AA6DD,wBAAsB,yBAAyB,IAAI,OAAO,CAAC,IAAI,CAAC,CAkD/D"}
1
+ {"version":3,"file":"CityConnection.d.ts","sourceRoot":"","sources":["../../src/shared/CityConnection.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAYH,OAAO,KAAK,EACV,uBAAuB,EAExB,MAAM,gCAAgC,CAAC;AAqBxC,wBAAgB,8BAA8B,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAEnF;AAcD,wBAAgB,2BAA2B,IAAI,uBAAuB,CA0BrE;AAED,wBAAgB,wBAAwB,CAAC,OAAO,CAAC,EAAE;IAAE,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,IAAI,CA8B9E;AAED,wBAAsB,kBAAkB,CAAC,OAAO,CAAC,EAAE;IAAE,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAuDvF;AAED,wBAAgB,kBAAkB,CAAC,OAAO,CAAC,EAAE;IAAE,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,IAAI,CA+BxE;AAED,wBAAsB,qBAAqB,CAAC,MAAM,EAAE;IAClD,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,GAAG,OAAO,CAAC,IAAI,CAAC,CA2BhB;AAED,wBAAsB,iBAAiB,CAAC,MAAM,EAAE;IAC9C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,GAAG,OAAO,CAAC,IAAI,CAAC,CAgChB;AAiBD,wBAAsB,mBAAmB,CAAC,MAAM,EAAE;IAChD,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,GAAG,OAAO,CAAC,IAAI,CAAC,CAoChB;AAED,wBAAgB,oBAAoB,CAAC,OAAO,CAAC,EAAE;IAAE,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,IAAI,CAiB1E;AAED,wBAAgB,wBAAwB,CAAC,OAAO,CAAC,EAAE;IAAE,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,IAAI,CAqB9E;AAkED,wBAAsB,yBAAyB,IAAI,OAAO,CAAC,IAAI,CAAC,CAsD/D"}
@@ -7,230 +7,20 @@
7
7
  * - Town 可以只读发现 `city` CLI 已配置的 base 地址,但不依赖 city 内部模块。
8
8
  * - CLI 命令装配统一放在 `src/command/CityCommand.ts`,本模块只保留状态与登录流程。
9
9
  */
10
- import fs from "node:fs";
11
- import os from "node:os";
12
- import path from "node:path";
13
10
  import prompts from "prompts";
14
- import { PlatformStore } from "../town/store/index.js";
15
11
  import { emitCliBlock, emitCliList } from "./CliReporter.js";
16
12
  import { printResult } from "../utils/cli/CliOutput.js";
17
13
  import { performTownCityUserLogin } from "./CityUserLogin.js";
18
14
  import { emitCurrentTownCityBalance, emitTownCityRechargeResult, rechargeCurrentTownCityUser, } from "./CityBalance.js";
19
- export const DEFAULT_CITY_URL = "https://base.downcity.ai";
20
- export const DEFAULT_TOWN_ID = "town_downcity";
21
- const CITY_CONFIG_PATH = path.join(os.homedir(), ".downcity", "config.json");
22
- const TOWN_CITY_STATE_KEY = "town.city.state";
15
+ import { CityUserManager } from "./CityUserManager.js";
16
+ import { DEFAULT_CITY_URL, DEFAULT_TOWN_ID, listTownCityServers, normalizeCityUrl, readCityAdminSecretForUrl, readCityString, readCurrentTownCitySession, readTownCityState, resolveSelectedBaseUrl, upsertTownProfile, writeTownCityState, } from "./CityStateStore.js";
17
+ const cityUserManager = new CityUserManager();
23
18
  function readString(value) {
24
- return typeof value === "string" ? value.trim() : "";
25
- }
26
- function defaultProtocol(value) {
27
- const host = value.split("/")[0] ?? "";
28
- const clean_host = host.split(":")[0] ?? "";
29
- if (clean_host === "localhost" ||
30
- clean_host.includes(":") ||
31
- clean_host.split(".").length === 4) {
32
- return "http";
33
- }
34
- return "https";
35
- }
36
- export function normalizeCityUrl(value) {
37
- const raw = String(value || "").trim();
38
- if (!raw)
39
- return "";
40
- const has_protocol = /^[a-z][a-z\d+.-]*:\/\//iu.test(raw);
41
- const with_protocol = has_protocol ? raw : `${defaultProtocol(raw)}://${raw}`;
42
- const url = new URL(with_protocol);
43
- if (!url.port &&
44
- (url.hostname === "localhost" || /^\d+\.\d+\.\d+\.\d+$/u.test(url.hostname))) {
45
- url.port = "43127";
46
- }
47
- return url.toString().replace(/\/+$/, "");
48
- }
49
- function deriveServerName(city_url) {
50
- try {
51
- return new URL(city_url).hostname || city_url;
52
- }
53
- catch {
54
- return city_url;
55
- }
56
- }
57
- function readJsonFile(file_path) {
58
- try {
59
- return JSON.parse(fs.readFileSync(file_path, "utf8"));
60
- }
61
- catch {
62
- return null;
63
- }
64
- }
65
- function normalizeLocalState(value) {
66
- const selected_base_url = normalizeCityUrl(readString(value?.selected_base_url));
67
- const profiles = [];
68
- for (const item of Array.isArray(value?.profiles) ? value.profiles : []) {
69
- const base_url = normalizeCityUrl(readString(item.base_url));
70
- if (!base_url || profiles.some((profile) => profile.base_url === base_url))
71
- continue;
72
- profiles.push({
73
- name: readString(item.name) || deriveServerName(base_url),
74
- base_url,
75
- });
76
- }
77
- const sessions = {};
78
- const input_sessions = value?.sessions && typeof value.sessions === "object"
79
- ? value.sessions
80
- : {};
81
- for (const [key, session] of Object.entries(input_sessions)) {
82
- const base_url = normalizeCityUrl(readString(session?.base_url) || key);
83
- const user_token = readString(session?.user_token);
84
- if (!base_url || !user_token)
85
- continue;
86
- sessions[base_url] = {
87
- base_url,
88
- town_id: readString(session?.town_id) || DEFAULT_TOWN_ID,
89
- user_id: readString(session?.user_id) || undefined,
90
- user_label: readString(session?.user_label) || undefined,
91
- user_token,
92
- updated_at: readString(session?.updated_at) || new Date().toISOString(),
93
- };
94
- }
95
- return {
96
- selected_base_url: selected_base_url || undefined,
97
- profiles,
98
- sessions,
99
- };
100
- }
101
- function readTownCityState() {
102
- const store = new PlatformStore();
103
- try {
104
- return normalizeLocalState(store.getSecureSettingJsonSync(TOWN_CITY_STATE_KEY));
105
- }
106
- finally {
107
- store.close();
108
- }
109
- }
110
- function writeTownCityState(state) {
111
- const store = new PlatformStore();
112
- try {
113
- store.setSecureSettingJsonSync(TOWN_CITY_STATE_KEY, normalizeLocalState(state));
114
- }
115
- finally {
116
- store.close();
117
- }
118
- }
119
- function readCityAdminConfig() {
120
- return readJsonFile(CITY_CONFIG_PATH) ?? {};
121
- }
122
- function readCityAdminServers() {
123
- const raw = readCityAdminConfig();
124
- const servers = Array.isArray(raw.servers) ? raw.servers : [];
125
- const active_url = normalizeCityUrl(readString(raw.active_server_url));
126
- const out = [];
127
- const state = readTownCityState();
128
- const selected_base_url = resolveSelectedBaseUrl(state);
129
- for (const item of servers) {
130
- const base_url = normalizeCityUrl(readString(item.base_url) || readString(item.url));
131
- if (!base_url || out.some((server) => server.base_url === base_url))
132
- continue;
133
- const session = state.sessions?.[base_url];
134
- out.push({
135
- name: readString(item.name) || deriveServerName(base_url),
136
- base_url,
137
- selected: base_url === selected_base_url,
138
- source: "city-admin",
139
- has_admin_secret_key: Boolean(readString(item.admin_secret_key)),
140
- has_user_session: Boolean(session?.user_token),
141
- town_id: session?.town_id,
142
- user_id: session?.user_id,
143
- });
144
- }
145
- return out.sort((left, right) => Number(right.base_url === active_url) - Number(left.base_url === active_url)
146
- || left.name.localeCompare(right.name)
147
- || left.base_url.localeCompare(right.base_url));
148
- }
149
- function readCityAdminSecretForUrl(city_url) {
150
- const target_url = normalizeCityUrl(city_url);
151
- const raw = readCityAdminConfig();
152
- const servers = Array.isArray(raw.servers) ? raw.servers : [];
153
- const matched = servers.find((item) => normalizeCityUrl(readString(item.base_url) || readString(item.url)) === target_url);
154
- return readString(matched?.admin_secret_key) || undefined;
19
+ return readCityString(value);
155
20
  }
156
21
  export function readTownCityAdminSecretForBase(city_url) {
157
22
  return readCityAdminSecretForUrl(city_url);
158
23
  }
159
- function resolveSelectedBaseUrl(state = readTownCityState()) {
160
- return normalizeCityUrl(readString(state.selected_base_url)) || DEFAULT_CITY_URL;
161
- }
162
- function upsertTownProfile(state, input) {
163
- const base_url = normalizeCityUrl(input.base_url);
164
- if (!base_url)
165
- return state;
166
- const profiles = [...(state.profiles ?? [])];
167
- const index = profiles.findIndex((item) => item.base_url === base_url);
168
- const profile = {
169
- name: readString(input.name) || deriveServerName(base_url),
170
- base_url,
171
- };
172
- if (index >= 0)
173
- profiles[index] = profile;
174
- else
175
- profiles.push(profile);
176
- return {
177
- ...state,
178
- selected_base_url: base_url,
179
- profiles,
180
- };
181
- }
182
- function listTownCityServers() {
183
- const state = readTownCityState();
184
- const selected_base_url = resolveSelectedBaseUrl(state);
185
- const admin_servers = readCityAdminServers();
186
- const by_url = new Map();
187
- const append = (profile) => {
188
- const existing = by_url.get(profile.base_url);
189
- if (!existing) {
190
- by_url.set(profile.base_url, profile);
191
- return;
192
- }
193
- by_url.set(profile.base_url, {
194
- ...existing,
195
- selected: existing.selected || profile.selected,
196
- source: existing.source === "town" ? "town" : profile.source,
197
- has_admin_secret_key: existing.has_admin_secret_key || profile.has_admin_secret_key,
198
- has_user_session: existing.has_user_session || profile.has_user_session,
199
- town_id: existing.town_id || profile.town_id,
200
- user_id: existing.user_id || profile.user_id,
201
- });
202
- };
203
- for (const profile of state.profiles ?? []) {
204
- const session = state.sessions?.[profile.base_url];
205
- append({
206
- name: profile.name,
207
- base_url: profile.base_url,
208
- selected: profile.base_url === selected_base_url,
209
- source: "town",
210
- has_admin_secret_key: Boolean(readCityAdminSecretForUrl(profile.base_url)),
211
- has_user_session: Boolean(session?.user_token),
212
- town_id: session?.town_id,
213
- user_id: session?.user_id,
214
- });
215
- }
216
- for (const server of admin_servers)
217
- append(server);
218
- const default_session = state.sessions?.[DEFAULT_CITY_URL];
219
- append({
220
- name: "Downcity Base",
221
- base_url: DEFAULT_CITY_URL,
222
- selected: DEFAULT_CITY_URL === selected_base_url,
223
- source: "default",
224
- has_admin_secret_key: Boolean(readCityAdminSecretForUrl(DEFAULT_CITY_URL)),
225
- has_user_session: Boolean(default_session?.user_token),
226
- town_id: default_session?.town_id,
227
- user_id: default_session?.user_id,
228
- });
229
- return [...by_url.values()].sort((left, right) => Number(right.selected) - Number(left.selected)
230
- || Number(right.source === "default") - Number(left.source === "default")
231
- || left.name.localeCompare(right.name)
232
- || left.base_url.localeCompare(right.base_url));
233
- }
234
24
  function findCityServer(input) {
235
25
  const query = String(input || "").trim();
236
26
  const servers = listTownCityServers();
@@ -241,23 +31,6 @@ function findCityServer(input) {
241
31
  server.base_url === normalized_query_url ||
242
32
  server.base_url === query) ?? null;
243
33
  }
244
- export function readCurrentTownCitySession() {
245
- const state = readTownCityState();
246
- const base_url = resolveSelectedBaseUrl(state);
247
- return state.sessions?.[base_url] ?? null;
248
- }
249
- export function readTownCityUserSessionForRuntime() {
250
- const state = readTownCityState();
251
- const city_url = resolveSelectedBaseUrl(state);
252
- const session = state.sessions?.[city_url] ?? null;
253
- if (!session?.user_token)
254
- return null;
255
- return {
256
- city_url,
257
- town_id: session.town_id || DEFAULT_TOWN_ID,
258
- user_token: session.user_token,
259
- };
260
- }
261
34
  export function readTownCityConnectionState() {
262
35
  const state = readTownCityState();
263
36
  const city_url = resolveSelectedBaseUrl(state);
@@ -314,6 +87,62 @@ export function emitCityConnectionStatus(options) {
314
87
  : "Run `town city login` to sign in as a City user.",
315
88
  });
316
89
  }
90
+ export async function emitCityUserWhoami(options) {
91
+ try {
92
+ const user = await cityUserManager.resolveCurrentUser();
93
+ if (options?.as_json === true) {
94
+ printResult({
95
+ asJson: true,
96
+ success: true,
97
+ title: "city user",
98
+ payload: {
99
+ city_url: user.city_url,
100
+ town_id: user.town_id,
101
+ user_id: user.user_id,
102
+ user_label: user.user_label,
103
+ source: user.source,
104
+ env_overrides: user.env_overrides,
105
+ warnings: user.warnings,
106
+ },
107
+ });
108
+ return;
109
+ }
110
+ emitCliBlock({
111
+ tone: "success",
112
+ title: "City user",
113
+ summary: user.source,
114
+ facts: [
115
+ { label: "url", value: user.city_url },
116
+ { label: "town", value: user.town_id },
117
+ { label: "user", value: user.user_id || "unknown" },
118
+ ...(user.user_label ? [{ label: "label", value: user.user_label }] : []),
119
+ { label: "source", value: user.source },
120
+ { label: "env url", value: user.env_overrides.city_url ? "yes" : "no" },
121
+ { label: "env town", value: user.env_overrides.town_id ? "yes" : "no" },
122
+ { label: "env token", value: user.env_overrides.user_token ? "yes" : "no" },
123
+ ],
124
+ note: user.warnings.join(" ") || undefined,
125
+ });
126
+ }
127
+ catch (error) {
128
+ if (options?.as_json === true) {
129
+ printResult({
130
+ asJson: true,
131
+ success: false,
132
+ title: "city user",
133
+ payload: {
134
+ error: error instanceof Error ? error.message : String(error),
135
+ },
136
+ });
137
+ return;
138
+ }
139
+ emitCliBlock({
140
+ tone: "error",
141
+ title: "City user unavailable",
142
+ note: error instanceof Error ? error.message : String(error),
143
+ });
144
+ }
145
+ }
317
146
  export function emitCityServerList(options) {
318
147
  const servers = listTownCityServers();
319
148
  if (options?.as_json === true) {
@@ -518,6 +347,11 @@ async function promptCityManagerAction() {
518
347
  description: state.has_user_token ? "重新登录当前 base" : "登录当前 base",
519
348
  value: "login",
520
349
  },
350
+ {
351
+ title: "查看当前 User",
352
+ description: "显示 Town 当前实际使用的 City user",
353
+ value: "whoami",
354
+ },
521
355
  {
522
356
  title: "查看 User 余额",
523
357
  description: state.has_user_token ? "读取当前登录 user 的余额" : "需要先登录 user",
@@ -582,14 +416,18 @@ export async function runInteractiveCityManager() {
582
416
  await runCityLoginCommand({});
583
417
  continue;
584
418
  }
419
+ if (action === "whoami") {
420
+ await emitCityUserWhoami();
421
+ continue;
422
+ }
585
423
  if (action === "balance") {
586
- await emitCurrentTownCityBalance(readCurrentTownCitySession());
424
+ await emitCurrentTownCityBalance();
587
425
  continue;
588
426
  }
589
427
  if (action === "recharge") {
590
428
  const input = await promptRechargeInput();
591
429
  if (input) {
592
- const result = await rechargeCurrentTownCityUser(readCurrentTownCitySession(), input);
430
+ const result = await rechargeCurrentTownCityUser(input);
593
431
  if (result)
594
432
  emitTownCityRechargeResult(result);
595
433
  }