ai_co_discuss 0.2.97 → 0.2.98

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/backend/admin.py CHANGED
@@ -127,7 +127,7 @@ def register_admin(connection, payload, setup_key, now):
127
127
  password = valid_password(payload.get("password"))
128
128
  supplied = payload.get("setup_key")
129
129
  setup = connection.execute("SELECT token_hash FROM admin_setup WHERE id=1").fetchone()
130
- # Either the install token or the one-time token written by `codiscuss admin token` registers.
130
+ # Either the install token or the one-time token written by `codiscuss token` registers.
131
131
  if not isinstance(supplied, str) or not (
132
132
  same_secret(supplied.strip(), setup_key)
133
133
  or setup and hmac.compare_digest(hashlib.sha256(supplied.strip().encode()).hexdigest(), setup["token_hash"])):
@@ -161,7 +161,7 @@ CREATE TABLE IF NOT EXISTS admin_sessions (
161
161
  token_hash TEXT PRIMARY KEY,
162
162
  created_at INTEGER NOT NULL
163
163
  );
164
- -- One-time registration token from `codiscuss admin token` on the deploying computer; cleared once the administrator registers.
164
+ -- One-time registration token from `codiscuss token` on the deploying computer; cleared once the administrator registers.
165
165
  CREATE TABLE IF NOT EXISTS admin_setup (
166
166
  id INTEGER PRIMARY KEY CHECK(id=1),
167
167
  token_hash TEXT NOT NULL,
@@ -96,10 +96,10 @@ Windows PowerShell 使用 `New-Item -ItemType Directory -Force -Path .wrangler/d
96
96
  ```sh
97
97
  npx wrangler d1 execute DB --remote --config .wrangler/deploy/wrangler.jsonc --file backend/schema.sql
98
98
  npm run deploy -- --cwd .wrangler/deploy
99
- codiscuss admin token
99
+ codiscuss token
100
100
  ```
101
101
 
102
- `codiscuss admin token` 生成注册管理员用的一次性令牌(需已 `wrangler login`),在网站左下角注册时填入;在已用 `codiscuss local connect` 连上本机的网页注册时,账号密码会保存到 `~/.codiscuss/admin-accounts.json`。注册后其他设备直接用账号密码登录。`schema.sql` 可重复执行;升级已有站点前请先备份 D1(`npx wrangler d1 export`)。
102
+ `codiscuss token` 生成注册管理员用的一次性令牌(需已 `wrangler login`),在网站左下角注册时填入;在已用 `codiscuss local connect` 连上本机的网页注册时,账号密码会保存到 `~/.codiscuss/admin-accounts.json`。注册后其他设备直接用账号密码登录。`schema.sql` 可重复执行;升级已有站点前请先备份 D1(`npx wrangler d1 export`)。
103
103
 
104
104
  发布后检查网页、`/api/health`,以及:
105
105
 
@@ -96,10 +96,10 @@ Keep the binding names `DB` and `ATTACHMENTS`. Without the R2 binding, text disc
96
96
  ```sh
97
97
  npx wrangler d1 execute DB --remote --config .wrangler/deploy/wrangler.jsonc --file backend/schema.sql
98
98
  npm run deploy -- --cwd .wrangler/deploy
99
- codiscuss admin token
99
+ codiscuss token
100
100
  ```
101
101
 
102
- `codiscuss admin token` prints a one-time token for registering the administrator (requires `wrangler login`); enter it when registering from the bottom-left corner. Registering from a page connected with `codiscuss local connect` also saves the account to `~/.codiscuss/admin-accounts.json`. Other devices then simply log in with the username and password. `schema.sql` is safe to re-run; back up D1 (`npx wrangler d1 export`) before upgrading an existing site.
102
+ `codiscuss token` prints a one-time token for registering the administrator (requires `wrangler login`); enter it when registering from the bottom-left corner. Registering from a page connected with `codiscuss local connect` also saves the account to `~/.codiscuss/admin-accounts.json`. Other devices then simply log in with the username and password. `schema.sql` is safe to re-run; back up D1 (`npx wrangler d1 export`) before upgrading an existing site.
103
103
 
104
104
  After publishing, check the page, `/api/health`, and:
105
105
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ai_co_discuss",
3
- "version": "0.2.97",
3
+ "version": "0.2.98",
4
4
  "bin": {
5
5
  "codiscuss": "runner/codiscuss.mjs"
6
6
  },
@@ -1,8 +1,7 @@
1
1
  /** Site administrator setup from the deploying computer: a one-time registration token and the saved account. */
2
2
  import { spawnSync } from 'node:child_process';
3
3
  import { createHash, randomBytes } from 'node:crypto';
4
- import { existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
5
- import { tmpdir } from 'node:os';
4
+ import { existsSync, mkdirSync, readFileSync } from 'node:fs';
6
5
  import { join, resolve } from 'node:path';
7
6
  import { parseArgs } from 'node:util';
8
7
 
@@ -12,11 +11,11 @@ import { service_home } from './discussion_service.mjs';
12
11
  const DEFAULT_CONFIG = join('.wrangler', 'deploy', 'wrangler.jsonc');
13
12
  const ACCOUNTS_FILE = 'admin-accounts.json';
14
13
  const TOKEN_BYTES = 32;
15
- const HELP = `用法:codiscuss admin token [--config WRANGLER_CONFIG]
14
+ const HELP = `用法:codiscuss token [--config WRANGLER_CONFIG]
16
15
 
17
- token 生成一次性管理员注册令牌,经 wrangler 把它的哈希写入线上 D1,立即生效。
18
- 在线上网页左下角注册管理员时填入;注册成功即作废,重新运行会替换旧令牌。
19
- 需要这台电脑已 wrangler login;--config 默认为当前目录的 ${DEFAULT_CONFIG}。
16
+ 生成一次性管理员注册令牌,经 wrangler 把它的哈希写入线上 D1,立即生效。
17
+ 在线上网页左下角注册管理员时填入;注册成功即作废,重新运行会替换旧令牌。
18
+ 需要这台电脑已 wrangler login;--config 默认为当前目录的 ${DEFAULT_CONFIG}。
20
19
 
21
20
  在已用 codiscuss local connect 连上本机服务的网页注册后,账号与密码保存在 ~/.codiscuss/${ACCOUNTS_FILE}。
22
21
  `;
@@ -27,12 +26,9 @@ export function create_admin_token(config, run = run_wrangler) {
27
26
  if (!existsSync(path)) throw new Error(`找不到部署配置 ${path};请在项目目录运行,或用 --config 指定 wrangler.jsonc`);
28
27
  const token = randomBytes(TOKEN_BYTES).toString('hex');
29
28
  const hashed = createHash('sha256').update(token).digest('hex');
30
- const directory = mkdtempSync(join(tmpdir(), 'codiscuss-admin-'));
31
- const sql = join(directory, 'admin-setup.sql');
32
- try {
33
- writeFileSync(sql, `INSERT OR REPLACE INTO admin_setup (id,token_hash,created_at) VALUES (1,'${hashed}',${Math.floor(Date.now() / 1000)});\n`);
34
- run(['d1', 'execute', 'DB', '--remote', '--config', path, '--file', sql]);
35
- } finally { rmSync(directory, { recursive: true, force: true }); }
29
+ // --command uses the ordinary query API; --file goes through D1's upload-based import, which fails behind some networks.
30
+ run(['d1', 'execute', 'DB', '--remote', '--config', path, '--command',
31
+ `INSERT OR REPLACE INTO admin_setup (id,token_hash,created_at) VALUES (1,'${hashed}',${Math.floor(Date.now() / 1000)})`]);
36
32
  return { token, config: path };
37
33
  }
38
34
 
@@ -55,12 +51,12 @@ export function save_admin_account(home, { site, username, password }) {
55
51
  return { saved: path };
56
52
  }
57
53
 
58
- /** `codiscuss admin ...` */
54
+ /** `codiscuss token [--config FILE]` */
59
55
  export function admin_main(args) {
60
56
  const { values, positionals } = parseArgs({ args, allowPositionals: true, options: {
61
57
  config: { type: 'string' }, help: { type: 'boolean', short: 'h' },
62
58
  } });
63
- if (values.help || positionals[0] !== 'token') return process.stdout.write(HELP);
59
+ if (values.help || positionals.length) return process.stdout.write(HELP);
64
60
  const { token } = create_admin_token(values.config);
65
61
  process.stdout.write(`管理员注册令牌(一次性):\n${token}\n\n在线上网页左下角注册管理员时填入。注册成功后作废;账号密码在已连接本机服务的网页注册时保存到 ${join(service_home(), ACCOUNTS_FILE)}。\n`);
66
62
  }
@@ -17,7 +17,7 @@ const HELP = `AI CoDiscuss CLI
17
17
  (无命令) 在当前终端启动服务,Ctrl+C 停止
18
18
  install / setup 安装持久命令并配置 / 配置已有安装
19
19
  local COMMAND 管理本机网站,或 connect 连接线上站点
20
- admin token 生成线上网站的一次性管理员注册令牌
20
+ token 生成线上网站的一次性管理员注册令牌
21
21
  service COMMAND 启动、停止、查询服务,或登记房间
22
22
  launch COMMAND 保存启动配置,或从 AI 对话启动讨论
23
23
  room COMMAND 创建、读取或更新讨论房间
@@ -120,7 +120,7 @@ async function main(args = process.argv.slice(2)) {
120
120
  if (command === 'launch') return launch_main(args.slice(1));
121
121
  if (['install', 'setup'].includes(command)) return setup_main(command, args.slice(1));
122
122
  if (command === 'local') return local_main(args.slice(1));
123
- if (command === 'admin') return admin_main(args.slice(1));
123
+ if (command === 'token') return admin_main(args.slice(1));
124
124
  if (!command || (command === 'run' && args.length === 1)) return service_cli([]);
125
125
  if (SERVICE_COMMANDS.has(command) || command === '--json') return service_cli(args);
126
126
  return website_cli(args);