c152f5fc1d
kbdb-base 8.P0:scheduled.ts cron 每分鐘 KV list → 單一 key get(lib/cron-index.ts); webhooks-named 維護單 key + 一次性 migrate-cron-index;acr update 自動遷移。1440 list/日 → 0。 self-hosted-init §7.8 onboarding: P0 init 偵測+裝完驗收(lib/preflight.ts,pip 式,冪等) P1 acr whoami(+--json)+ MCP arcrun_whoami(AI 不繞 CLI 猜帳號) P2 mcp-setup 寫完印「請重啟 client」 P3(部分)repo .env.example 範本(每格白話說明、值留空)+ llms.txt 教 AI 幫用戶 cp 建 .env Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
78 lines
3.1 KiB
TypeScript
78 lines
3.1 KiB
TypeScript
/**
|
||
* acr whoami — 一眼看「我現在是誰、連哪台、帳號從哪層來」(§7.8 P1,D2 修法)。
|
||
*
|
||
* D2 根因(self-hosted-init.md §7.8):config 分層**已實作**(config.ts),但 AI 不用 CLI 讀帳號、
|
||
* 自己 curl 猜全域帳號 URL → 打到錯帳號。治本不是再改 config,是給 AI 一個無腦入口:
|
||
* 「問 CLI 拿正確身份,別自己 curl 猜」。與 MCP arcrun_whoami 對齊(薄殼一致,rule 07 §5)。
|
||
*
|
||
* 與 acr config 區別:config 印完整欄位表(人用、含敏感欄位遮罩);whoami 印精煉摘要
|
||
* (mode / 連哪台 cypher / 帳號來源層),AI 讀完就知道該用哪個帳號、打哪個 URL,不必再猜。
|
||
*
|
||
* --json:給 AI/MCP 結構化讀取(薄殼一致)。
|
||
*/
|
||
import chalk from 'chalk';
|
||
import {
|
||
loadConfig,
|
||
resolveConfigSources,
|
||
getCypherExecutorUrl,
|
||
getMcpUrl,
|
||
activeProjectConfigPath,
|
||
type ConfigSource,
|
||
} from '../lib/config.js';
|
||
|
||
const SOURCE_LABEL: Record<ConfigSource, string> = {
|
||
env: 'env 變數',
|
||
project: '專案層 .arcrun.yaml',
|
||
global: '全域 ~/.arcrun/config.yaml',
|
||
default: '預設值',
|
||
};
|
||
|
||
/** 帳號身份欄位(self-hosted=api_key 即 NAMESPACE 分區標籤;standard=平台 api_key)。*/
|
||
function identitySource(): ConfigSource {
|
||
const row = resolveConfigSources().find((r) => r.field === 'api_key');
|
||
return row?.source ?? 'default';
|
||
}
|
||
|
||
function maskKey(v?: string): string {
|
||
if (!v) return '(未設)';
|
||
return v.length > 8 ? `${v.slice(0, 8)}…` : v;
|
||
}
|
||
|
||
export async function cmdWhoami(options: { json?: boolean }): Promise<void> {
|
||
const config = loadConfig();
|
||
const cypherUrl = getCypherExecutorUrl(config);
|
||
const mcpUrl = getMcpUrl(config);
|
||
const accountSource = identitySource();
|
||
const projectPath = activeProjectConfigPath();
|
||
|
||
if (options.json) {
|
||
// 結構化輸出(AI/MCP 對齊用)。敏感值不全印。
|
||
console.log(JSON.stringify({
|
||
mode: config.mode,
|
||
account: maskKey(config.api_key),
|
||
account_source: accountSource,
|
||
cypher_executor_url: cypherUrl,
|
||
mcp_url: mcpUrl,
|
||
cloudflare_account_id: config.cloudflare_account_id ?? null,
|
||
project_config: projectPath ?? null,
|
||
}, null, 2));
|
||
return;
|
||
}
|
||
|
||
console.log(chalk.bold('\n arcrun — 目前身份\n'));
|
||
console.log(` ${chalk.cyan('模式')} ${config.mode}`);
|
||
console.log(` ${chalk.cyan('帳號')} ${maskKey(config.api_key)} ${chalk.gray(`← ${SOURCE_LABEL[accountSource]}`)}`);
|
||
console.log(` ${chalk.cyan('連哪台')} ${cypherUrl}`);
|
||
console.log(` ${chalk.cyan('MCP')} ${mcpUrl}`);
|
||
if (config.mode === 'self-hosted' && config.cloudflare_account_id) {
|
||
console.log(` ${chalk.cyan('CF 帳號')} ${config.cloudflare_account_id}`);
|
||
}
|
||
console.log('');
|
||
if (projectPath) {
|
||
console.log(chalk.gray(` 此資料夾用專案層設定:${projectPath}`));
|
||
} else {
|
||
console.log(chalk.gray(' 此資料夾用全域設定(無 .arcrun.yaml)'));
|
||
}
|
||
console.log(chalk.gray(' → 部署/觸發前用這個帳號,別自己 curl 全域 URL 猜帳號。\n'));
|
||
}
|