agent-auth-broker 0.0.2
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/index.js +2064 -0
- package/dist/index.js.map +1 -0
- package/package.json +46 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/commands/init.ts","../src/utils.ts","../src/commands/validate.ts","../../../packages/local-runtime/src/config-loader.ts","../../../packages/local-runtime/src/local-store.ts","../../../packages/connectors/src/github/index.ts","../../../packages/connectors/src/registry.ts","../../../packages/connectors/src/scopes.ts","../../../packages/local-runtime/src/rate-limiter.ts","../../../packages/local-runtime/src/local-permission.ts","../../../packages/crypto/src/index.ts","../../../packages/local-runtime/src/local-vault.ts","../../../packages/local-runtime/src/local-audit.ts","../../../packages/local-runtime/src/local-broker.ts","../../../packages/local-runtime/src/token-auth.ts","../../../packages/local-runtime/src/config-watcher.ts","../src/commands/diagnose.ts","../src/commands/serve.ts","../src/commands/credential.ts","../src/commands/agent.ts","../src/commands/policy.ts","../src/commands/ui.ts","../src/ui/server.ts","../src/ui/html.ts","../src/ui/handlers.ts","../src/commands/token.ts","../src/commands/test.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { Command } from 'commander'\nimport { initCommand } from './commands/init.js'\nimport { validateCommand } from './commands/validate.js'\nimport { diagnoseCommand } from './commands/diagnose.js'\nimport { serveCommand } from './commands/serve.js'\nimport { credentialCommand } from './commands/credential.js'\nimport { agentCommand } from './commands/agent.js'\nimport { policyCommand } from './commands/policy.js'\nimport { uiCommand } from './commands/ui.js'\nimport { tokenCommand } from './commands/token.js'\nimport { testCommand } from './commands/test.js'\n\nconst program = new Command()\n\nprogram\n .name('broker')\n .description('Agent Auth Broker CLI — AI Agent 凭证管理与授权代理')\n .version('0.0.1')\n\nprogram.addCommand(initCommand)\nprogram.addCommand(validateCommand)\nprogram.addCommand(diagnoseCommand)\nprogram.addCommand(serveCommand)\nprogram.addCommand(credentialCommand)\nprogram.addCommand(agentCommand)\nprogram.addCommand(policyCommand)\nprogram.addCommand(uiCommand)\nprogram.addCommand(tokenCommand)\nprogram.addCommand(testCommand)\n\nprogram.parse()\n","import fs from 'node:fs'\nimport { Command } from 'commander'\nimport { stringify as stringifyYaml } from 'yaml'\nimport { resolveConfigPath, logSuccess, logError, logWarn } from '../utils.js'\n\nexport const initCommand = new Command('init')\n .description('初始化 broker.yaml 配置文件')\n .option('-c, --config <path>', '配置文件路径', undefined)\n .option('--force', '覆盖已存在的配置文件', false)\n .action((opts: { config?: string; force: boolean }) => {\n const configPath = resolveConfigPath(opts.config)\n\n if (fs.existsSync(configPath) && !opts.force) {\n logWarn(`配置文件已存在: ${configPath}`)\n logWarn('使用 --force 覆盖')\n return\n }\n\n const template = {\n version: '1',\n agents: [\n {\n id: 'my-agent',\n name: 'My AI Agent',\n },\n ],\n credentials: [\n {\n id: 'github-main',\n connector: 'github',\n token: '${GITHUB_TOKEN}',\n },\n ],\n policies: [\n {\n agent: 'my-agent',\n credential: 'github-main',\n actions: ['*'],\n },\n ],\n audit: {\n enabled: true,\n output: 'stdout',\n },\n }\n\n const yaml = stringifyYaml(template, { lineWidth: 120 })\n fs.writeFileSync(configPath, yaml, 'utf-8')\n logSuccess(`已创建配置文件: ${configPath}`)\n log_hint()\n })\n\nfunction log_hint(): void {\n console.log(`\n下一步:\n 1. 设置环境变量: export GITHUB_TOKEN=your_token\n 2. 验证配置: broker validate\n 3. 诊断连接: broker diagnose\n 4. 启动服务: broker serve\n`)\n}\n","import fs from 'node:fs'\nimport path from 'node:path'\nimport { parse as parseYaml, stringify as stringifyYaml } from 'yaml'\n\nconst DEFAULT_CONFIG_NAME = 'broker.yaml'\n\n/**\n * 查找配置文件路径\n * 优先使用 --config 参数,否则从当前目录向上查找 broker.yaml\n */\nexport function resolveConfigPath(configOption?: string): string {\n if (configOption) {\n return path.resolve(configOption)\n }\n\n let dir = process.cwd()\n while (true) {\n const candidate = path.join(dir, DEFAULT_CONFIG_NAME)\n if (fs.existsSync(candidate)) return candidate\n const parent = path.dirname(dir)\n if (parent === dir) break\n dir = parent\n }\n\n return path.resolve(DEFAULT_CONFIG_NAME)\n}\n\n/**\n * 读取 YAML 配置文件(原始对象,不解析环境变量)\n */\nexport function readRawConfig(configPath: string): Record<string, unknown> {\n if (!fs.existsSync(configPath)) {\n throw new Error(`配置文件不存在: ${configPath}`)\n }\n const raw = fs.readFileSync(configPath, 'utf-8')\n return parseYaml(raw) as Record<string, unknown>\n}\n\n/**\n * 写入 YAML 配置文件\n */\nexport function writeConfig(configPath: string, config: Record<string, unknown>): void {\n const yaml = stringifyYaml(config, { lineWidth: 120 })\n fs.writeFileSync(configPath, yaml, 'utf-8')\n}\n\nexport function log(message: string): void {\n console.log(message)\n}\n\nexport function logError(message: string): void {\n console.error(`\\u274C ${message}`)\n}\n\nexport function logSuccess(message: string): void {\n console.log(`\\u2705 ${message}`)\n}\n\nexport function logWarn(message: string): void {\n console.log(`\\u26A0\\uFE0F ${message}`)\n}\n","import { Command } from 'commander'\nimport { validateConfigFile } from '@broker/local-runtime'\nimport { resolveConfigPath, logSuccess, logError } from '../utils.js'\n\nexport const validateCommand = new Command('validate')\n .description('验证 broker.yaml 配置文件格式')\n .option('-c, --config <path>', '配置文件路径', undefined)\n .action((opts: { config?: string }) => {\n const configPath = resolveConfigPath(opts.config)\n console.log(`验证配置文件: ${configPath}`)\n\n const { valid, errors } = validateConfigFile(configPath)\n\n if (valid) {\n logSuccess('配置文件格式正确')\n } else {\n logError('配置文件存在以下问题:')\n for (const err of errors) {\n console.log(` - ${err}`)\n }\n process.exitCode = 1\n }\n })\n","import fs from 'node:fs'\nimport path from 'node:path'\nimport { parse as parseYaml } from 'yaml'\nimport { z } from 'zod'\n\nconst RateLimitSchema = z.object({\n max_calls: z.number().int().positive(),\n window_seconds: z.number().int().positive(),\n}).optional()\n\nconst ParamConstraintSchema = z.record(\n z.string(),\n z.object({ pattern: z.string().optional() })\n)\n\nconst AgentSchema = z.object({\n id: z.string().min(1),\n name: z.string().min(1),\n token_hash: z.string().optional(),\n token_prefix: z.string().optional(),\n})\n\nconst CredentialSchema = z.object({\n id: z.string().min(1),\n connector: z.string().min(1),\n token: z.string().optional(),\n encrypted: z.string().optional(),\n})\n\nconst PolicySchema = z.object({\n agent: z.string().min(1),\n credential: z.string().min(1),\n actions: z.array(z.string()).default(['*']),\n param_constraints: ParamConstraintSchema.optional(),\n rate_limit: RateLimitSchema,\n expires_at: z.string().datetime().optional(),\n})\n\nconst AuditSchema = z.object({\n enabled: z.boolean().default(true),\n output: z.enum(['stdout', 'file']).default('stdout'),\n file: z.string().optional(),\n}).default({ enabled: true, output: 'stdout' })\n\nconst BrokerConfigSchema = z.object({\n version: z.string().default('1'),\n encryption_key: z.string().optional(),\n agents: z.array(AgentSchema).min(1),\n credentials: z.array(CredentialSchema).min(1),\n policies: z.array(PolicySchema).min(1),\n audit: AuditSchema,\n})\n\nexport type BrokerConfig = z.infer<typeof BrokerConfigSchema>\nexport type AgentConfig = z.infer<typeof AgentSchema>\nexport type CredentialConfig = z.infer<typeof CredentialSchema>\nexport type PolicyConfig = z.infer<typeof PolicySchema>\nexport type AuditConfig = z.infer<typeof AuditSchema>\n\n/**\n * 解析字符串中的 ${ENV_VAR} 引用\n */\nfunction resolveEnvVars(value: string): string {\n return value.replace(/\\$\\{([^}]+)\\}/g, (_, envName: string) => {\n const envValue = process.env[envName]\n if (envValue === undefined) {\n throw new Error(`环境变量 ${envName} 未设置`)\n }\n return envValue\n })\n}\n\n/**\n * 递归解析对象中的所有 ${ENV_VAR} 引用\n */\nfunction resolveEnvVarsInObject<T>(obj: T): T {\n if (typeof obj === 'string') {\n return resolveEnvVars(obj) as T\n }\n if (Array.isArray(obj)) {\n return obj.map(item => resolveEnvVarsInObject(item)) as T\n }\n if (obj !== null && typeof obj === 'object') {\n const result: Record<string, unknown> = {}\n for (const [key, value] of Object.entries(obj as Record<string, unknown>)) {\n result[key] = resolveEnvVarsInObject(value)\n }\n return result as T\n }\n return obj\n}\n\n/**\n * 从文件路径加载 broker.yaml 配置\n */\nexport function loadConfig(configPath: string): BrokerConfig {\n const absolutePath = path.resolve(configPath)\n if (!fs.existsSync(absolutePath)) {\n throw new Error(`配置文件不存在: ${absolutePath}`)\n }\n\n const raw = fs.readFileSync(absolutePath, 'utf-8')\n const parsed = parseYaml(raw)\n const resolved = resolveEnvVarsInObject(parsed)\n const result = BrokerConfigSchema.parse(resolved)\n\n // 验证凭证配置完整性\n for (const cred of result.credentials) {\n if (!cred.token && !cred.encrypted) {\n throw new Error(`凭证 \"${cred.id}\" 必须设置 token 或 encrypted 字段`)\n }\n if (cred.encrypted && !result.encryption_key) {\n throw new Error(`凭证 \"${cred.id}\" 使用加密存储,但未设置 encryption_key`)\n }\n }\n\n // 验证策略引用完整性\n const agentIds = new Set(result.agents.map(a => a.id))\n const credentialIds = new Set(result.credentials.map(c => c.id))\n\n for (const policy of result.policies) {\n if (!agentIds.has(policy.agent)) {\n throw new Error(`策略引用了不存在的 agent: \"${policy.agent}\"`)\n }\n if (!credentialIds.has(policy.credential)) {\n throw new Error(`策略引用了不存在的 credential: \"${policy.credential}\"`)\n }\n }\n\n return result\n}\n\n/**\n * 验证配置文件格式(不解析环境变量,只检查结构)\n */\nexport function validateConfigFile(configPath: string): { valid: boolean; errors: string[] } {\n const errors: string[] = []\n\n try {\n const absolutePath = path.resolve(configPath)\n if (!fs.existsSync(absolutePath)) {\n return { valid: false, errors: [`配置文件不存在: ${absolutePath}`] }\n }\n\n const raw = fs.readFileSync(absolutePath, 'utf-8')\n const parsed = parseYaml(raw)\n\n // 用 safeParse 收集所有错误\n const result = BrokerConfigSchema.safeParse(parsed)\n if (!result.success) {\n for (const issue of result.error.issues) {\n errors.push(`${issue.path.join('.')}: ${issue.message}`)\n }\n }\n } catch (err) {\n errors.push(err instanceof Error ? err.message : String(err))\n }\n\n return { valid: errors.length === 0, errors }\n}\n","import type { BrokerConfig, AgentConfig, CredentialConfig, PolicyConfig, AuditConfig } from './config-loader.js'\n\n/**\n * 内存数据存储,从 broker.yaml 配置加载\n * 替代数据库模式下的 Prisma ORM\n */\nexport class LocalStore {\n private agents: Map<string, AgentConfig>\n private credentials: Map<string, CredentialConfig>\n private policies: PolicyConfig[]\n readonly audit: AuditConfig\n readonly encryptionKey: string | undefined\n\n constructor(config: BrokerConfig) {\n this.agents = new Map(config.agents.map(a => [a.id, a]))\n this.credentials = new Map(config.credentials.map(c => [c.id, c]))\n this.policies = config.policies\n this.audit = config.audit\n this.encryptionKey = config.encryption_key\n }\n\n getAgent(id: string): AgentConfig | undefined {\n return this.agents.get(id)\n }\n\n listAgents(): AgentConfig[] {\n return Array.from(this.agents.values())\n }\n\n getCredential(id: string): CredentialConfig | undefined {\n return this.credentials.get(id)\n }\n\n listCredentials(): CredentialConfig[] {\n return Array.from(this.credentials.values())\n }\n\n /**\n * 查找 agent 对 connector 的策略\n */\n findPolicy(agentId: string, connectorId: string): PolicyConfig | undefined {\n return this.policies.find(p => {\n if (p.agent !== agentId) return false\n const cred = this.credentials.get(p.credential)\n if (!cred || cred.connector !== connectorId) return false\n if (p.expires_at && new Date(p.expires_at) < new Date()) return false\n return true\n })\n }\n\n /**\n * 获取 agent 的所有活跃策略\n */\n getAgentPolicies(agentId: string): Array<PolicyConfig & { credentialConfig: CredentialConfig }> {\n const result: Array<PolicyConfig & { credentialConfig: CredentialConfig }> = []\n\n for (const policy of this.policies) {\n if (policy.agent !== agentId) continue\n if (policy.expires_at && new Date(policy.expires_at) < new Date()) continue\n\n const cred = this.credentials.get(policy.credential)\n if (!cred) continue\n\n result.push({ ...policy, credentialConfig: cred })\n }\n\n return result\n }\n\n /**\n * 通过 token hash 查找对应的 agent\n */\n findAgentByTokenHash(hash: string): AgentConfig | undefined {\n return this.listAgents().find(a => a.token_hash === hash)\n }\n\n /**\n * 重新加载配置\n */\n reload(config: BrokerConfig): void {\n this.agents = new Map(config.agents.map(a => [a.id, a]))\n this.credentials = new Map(config.credentials.map(c => [c.id, c]))\n this.policies = config.policies\n ;(this as { audit: AuditConfig }).audit = config.audit\n ;(this as { encryptionKey: string | undefined }).encryptionKey = config.encryption_key\n }\n}\n","import type { ConnectorAdapter, ConnectorAction, ConnectorResult, DecryptedCredential } from '../types'\n\nconst GITHUB_API = 'https://api.github.com'\n\nasync function githubRequest(\n method: string,\n path: string,\n token: string,\n body?: unknown\n): Promise<{ status: number; data: unknown }> {\n const res = await fetch(`${GITHUB_API}${path}`, {\n method,\n headers: {\n Authorization: `Bearer ${token}`,\n Accept: 'application/vnd.github.v3+json',\n 'Content-Type': 'application/json',\n 'User-Agent': 'agent-auth-broker/1.0',\n },\n body: body ? JSON.stringify(body) : undefined,\n })\n const data = await res.json().catch(() => ({}))\n return { status: res.status, data }\n}\n\nfunction ok(data: unknown, status?: number): ConnectorResult {\n return { success: true, data, httpStatus: status }\n}\n\nfunction fail(message: string, code: string, status?: number): ConnectorResult {\n return { success: false, error: { code, message }, httpStatus: status }\n}\n\nexport const githubConnector: ConnectorAdapter = {\n info: {\n id: 'github',\n name: 'GitHub',\n description: 'GitHub 仓库、Issue、PR 操作',\n authType: 'oauth2',\n },\n\n getActions(): ConnectorAction[] {\n return [\n { id: 'list_repos', name: '列出仓库', description: '列出已授权用户的仓库', inputSchema: { type: 'object', properties: { per_page: { type: 'number' }, page: { type: 'number' } } } },\n { id: 'get_repo', name: '获取仓库', description: '获取仓库信息', inputSchema: { type: 'object', required: ['repo'], properties: { repo: { type: 'string', description: 'owner/repo' } } } },\n { id: 'list_issues', name: '列出 Issue', description: '列出仓库的 Issue', inputSchema: { type: 'object', required: ['repo'], properties: { repo: { type: 'string' }, state: { type: 'string', enum: ['open', 'closed', 'all'] }, per_page: { type: 'number' } } } },\n { id: 'get_issue', name: '获取 Issue', description: '获取单个 Issue 详情', inputSchema: { type: 'object', required: ['repo', 'issue_number'], properties: { repo: { type: 'string' }, issue_number: { type: 'number' } } } },\n { id: 'create_issue', name: '创建 Issue', description: '在仓库中创建 Issue', inputSchema: { type: 'object', required: ['repo', 'title'], properties: { repo: { type: 'string' }, title: { type: 'string' }, body: { type: 'string' }, labels: { type: 'array', items: { type: 'string' } } } } },\n { id: 'comment_issue', name: '评论 Issue', description: '在 Issue 上添加评论', inputSchema: { type: 'object', required: ['repo', 'issue_number', 'body'], properties: { repo: { type: 'string' }, issue_number: { type: 'number' }, body: { type: 'string' } } } },\n { id: 'list_prs', name: '列出 PR', description: '列出仓库的 Pull Request', inputSchema: { type: 'object', required: ['repo'], properties: { repo: { type: 'string' }, state: { type: 'string', enum: ['open', 'closed', 'all'] }, per_page: { type: 'number' } } } },\n { id: 'create_pr', name: '创建 PR', description: '创建 Pull Request', inputSchema: { type: 'object', required: ['repo', 'title', 'head', 'base'], properties: { repo: { type: 'string' }, title: { type: 'string' }, head: { type: 'string' }, base: { type: 'string' }, body: { type: 'string' }, draft: { type: 'boolean' } } } },\n { id: 'get_file', name: '获取文件', description: '获取仓库中的文件内容', inputSchema: { type: 'object', required: ['repo', 'path'], properties: { repo: { type: 'string' }, path: { type: 'string' }, ref: { type: 'string' } } } },\n { id: 'search_code', name: '搜索代码', description: '在 GitHub 上搜索代码', inputSchema: { type: 'object', required: ['q'], properties: { q: { type: 'string' }, per_page: { type: 'number' } } } },\n ]\n },\n\n async execute(\n action: string,\n params: Record<string, unknown>,\n credential: DecryptedCredential\n ): Promise<ConnectorResult> {\n const token = credential.accessToken\n\n switch (action) {\n case 'list_repos': {\n const { per_page = 30, page = 1 } = params\n const r = await githubRequest('GET', `/user/repos?per_page=${per_page}&page=${page}&sort=updated`, token)\n return r.status === 200 ? ok(r.data, r.status) : fail('Failed to list repos', 'GITHUB_ERROR', r.status)\n }\n\n case 'get_repo': {\n const r = await githubRequest('GET', `/repos/${params.repo}`, token)\n return r.status === 200 ? ok(r.data, r.status) : fail('Repo not found', 'NOT_FOUND', r.status)\n }\n\n case 'list_issues': {\n const { repo, state = 'open', per_page = 30 } = params\n const r = await githubRequest('GET', `/repos/${repo}/issues?state=${state}&per_page=${per_page}`, token)\n return r.status === 200 ? ok(r.data, r.status) : fail('Failed to list issues', 'GITHUB_ERROR', r.status)\n }\n\n case 'get_issue': {\n const r = await githubRequest('GET', `/repos/${params.repo}/issues/${params.issue_number}`, token)\n return r.status === 200 ? ok(r.data, r.status) : fail('Issue not found', 'NOT_FOUND', r.status)\n }\n\n case 'create_issue': {\n const { repo, ...body } = params\n const r = await githubRequest('POST', `/repos/${repo}/issues`, token, body)\n return r.status === 201 ? ok(r.data, r.status) : fail('Failed to create issue', 'GITHUB_ERROR', r.status)\n }\n\n case 'comment_issue': {\n const { repo, issue_number, body } = params\n const r = await githubRequest('POST', `/repos/${repo}/issues/${issue_number}/comments`, token, { body })\n return r.status === 201 ? ok(r.data, r.status) : fail('Failed to add comment', 'GITHUB_ERROR', r.status)\n }\n\n case 'list_prs': {\n const { repo, state = 'open', per_page = 30 } = params\n const r = await githubRequest('GET', `/repos/${repo}/pulls?state=${state}&per_page=${per_page}`, token)\n return r.status === 200 ? ok(r.data, r.status) : fail('Failed to list PRs', 'GITHUB_ERROR', r.status)\n }\n\n case 'create_pr': {\n const { repo, ...body } = params\n const r = await githubRequest('POST', `/repos/${repo}/pulls`, token, body)\n return r.status === 201 ? ok(r.data, r.status) : fail('Failed to create PR', 'GITHUB_ERROR', r.status)\n }\n\n case 'get_file': {\n const { repo, path, ref } = params\n const query = ref ? `?ref=${ref}` : ''\n const r = await githubRequest('GET', `/repos/${repo}/contents/${path}${query}`, token)\n if (r.status === 200) {\n const file = r.data as { content?: string; encoding?: string; [k: string]: unknown }\n if (file.content && file.encoding === 'base64') {\n file.content = Buffer.from(file.content.replace(/\\n/g, ''), 'base64').toString('utf8')\n }\n return ok(file, r.status)\n }\n return fail('File not found', 'NOT_FOUND', r.status)\n }\n\n case 'search_code': {\n const { q, per_page = 10 } = params\n const r = await githubRequest('GET', `/search/code?q=${encodeURIComponent(q as string)}&per_page=${per_page}`, token)\n return r.status === 200 ? ok(r.data, r.status) : fail('Search failed', 'GITHUB_ERROR', r.status)\n }\n\n default:\n return fail(`Unknown action: ${action}`, 'UNKNOWN_ACTION')\n }\n },\n}\n","import type { ConnectorAdapter } from './types'\nimport { githubConnector } from './github/index'\n\nconst connectors = new Map<string, ConnectorAdapter>([\n ['github', githubConnector],\n])\n\nexport function getConnector(id: string): ConnectorAdapter | undefined {\n return connectors.get(id)\n}\n\nexport function listConnectors(): ConnectorAdapter[] {\n return Array.from(connectors.values())\n}\n\nexport function registerConnector(adapter: ConnectorAdapter): void {\n connectors.set(adapter.info.id, adapter)\n}\n","/**\n * 预定义的 scope 组,将一个 scope 名称展开为多个具体 actions\n * 格式:{ connectorId: { scopeName: [actions] } }\n */\nconst CONNECTOR_SCOPES: Record<string, Record<string, string[]>> = {\n github: {\n 'github:read': [\n 'github:list_repos',\n 'github:get_repo',\n 'github:list_issues',\n 'github:get_issue',\n 'github:list_prs',\n 'github:get_file',\n 'github:search_code',\n ],\n 'github:write': [\n 'github:create_issue',\n 'github:comment_issue',\n 'github:create_pr',\n ],\n },\n}\n\n/**\n * 展开 scope 组为具体 actions\n * - \"*\" 保持不变\n * - \"github:read\" 等 scope 名称展开为对应的 actions 列表\n * - 已经是具体 action(如 \"github:list_repos\")则保持不变\n */\nexport function expandScopes(actions: string[]): string[] {\n if (actions.length === 1 && actions[0] === '*') return actions\n\n const expanded = new Set<string>()\n for (const action of actions) {\n // 检查是否是已知的 scope\n let found = false\n for (const scopes of Object.values(CONNECTOR_SCOPES)) {\n if (action in scopes) {\n for (const a of scopes[action]) {\n expanded.add(a)\n }\n found = true\n break\n }\n }\n if (!found) {\n expanded.add(action)\n }\n }\n return Array.from(expanded)\n}\n\n/**\n * 获取所有已知的 scope 名称\n */\nexport function listScopes(): Array<{ scope: string; actions: string[] }> {\n const result: Array<{ scope: string; actions: string[] }> = []\n for (const scopes of Object.values(CONNECTOR_SCOPES)) {\n for (const [scope, actions] of Object.entries(scopes)) {\n result.push({ scope, actions })\n }\n }\n return result\n}\n","/**\n * 内存滑动窗口速率限制器\n * 基于 policy 的 rate_limit 配置进行限速\n */\n\ninterface RateLimitConfig {\n max_calls: number\n window_seconds: number\n}\n\ninterface WindowEntry {\n timestamps: number[]\n}\n\nexport class RateLimiter {\n /** key = `${agentId}:${credentialId}` */\n private windows: Map<string, WindowEntry> = new Map()\n\n /**\n * 检查是否允许请求\n * @returns { allowed: true } 或 { allowed: false, retryAfterMs }\n */\n check(\n agentId: string,\n credentialId: string,\n config: RateLimitConfig\n ): { allowed: true } | { allowed: false; retryAfterMs: number } {\n const key = `${agentId}:${credentialId}`\n const now = Date.now()\n const windowMs = config.window_seconds * 1000\n const windowStart = now - windowMs\n\n let entry = this.windows.get(key)\n if (!entry) {\n entry = { timestamps: [] }\n this.windows.set(key, entry)\n }\n\n // 清理过期的时间戳\n entry.timestamps = entry.timestamps.filter(t => t > windowStart)\n\n if (entry.timestamps.length >= config.max_calls) {\n // 计算最早的时间戳何时过期\n const earliest = entry.timestamps[0]\n const retryAfterMs = earliest + windowMs - now\n return { allowed: false, retryAfterMs: Math.max(retryAfterMs, 0) }\n }\n\n // 记录当前请求\n entry.timestamps.push(now)\n return { allowed: true }\n }\n\n /**\n * 清除所有计数器\n */\n reset(): void {\n this.windows.clear()\n }\n}\n","import type { PermissionCheckInput, PermissionCheckResult } from '@broker/shared-types'\nimport { expandScopes } from '@broker/connectors'\nimport type { LocalStore } from './local-store.js'\nimport { RateLimiter } from './rate-limiter.js'\n\n// 全局速率限制器实例(跨调用保持状态)\nconst globalRateLimiter = new RateLimiter()\n\n/**\n * 基于内存配置的权限检查\n * 逻辑与 @broker/core 的 checkPermission 一致,但数据源为 LocalStore\n */\nexport function checkLocalPermission(\n input: PermissionCheckInput,\n store: LocalStore\n): PermissionCheckResult {\n const { agentId, connectorId, action } = input\n const fullAction = `${connectorId}:${action}`\n\n // 1. 检查 Agent 是否存在\n const agent = store.getAgent(agentId)\n if (!agent) {\n return { result: 'DENIED_AGENT_INACTIVE', message: 'Agent 不存在' }\n }\n\n // 2. 查找匹配的策略(findPolicy 已含过期检查)\n const policy = store.findPolicy(agentId, connectorId)\n if (!policy) {\n return { result: 'DENIED_NO_POLICY', message: `未找到 agent \"${agentId}\" 对 connector \"${connectorId}\" 的策略` }\n }\n\n // 3. 二次过期检查(防止 findPolicy 和 permission 逻辑分离导致遗漏)\n if (policy.expires_at && new Date(policy.expires_at) < new Date()) {\n return { result: 'DENIED_NO_POLICY', message: `策略已过期(${policy.expires_at})` }\n }\n\n // 4. 检查 allowedActions([\"*\"] 或空数组 = 允许所有),支持 scope 展开\n const expandedActions = expandScopes(policy.actions)\n const actionsAllowAll = expandedActions.length === 0\n || (expandedActions.length === 1 && expandedActions[0] === '*')\n\n if (!actionsAllowAll && !expandedActions.includes(fullAction)) {\n return {\n result: 'DENIED_ACTION_NOT_ALLOWED',\n message: `操作 \"${fullAction}\" 不在允许列表中`,\n }\n }\n\n // 5. 检查参数约束\n if (policy.param_constraints && input.params) {\n for (const [key, constraint] of Object.entries(policy.param_constraints)) {\n const paramValue = input.params[key]\n if (constraint.pattern && typeof paramValue === 'string') {\n const regex = new RegExp(constraint.pattern)\n if (!regex.test(paramValue)) {\n return {\n result: 'DENIED_PARAM_CONSTRAINT',\n message: `参数 \"${key}\" 的值 \"${paramValue}\" 不匹配模式 \"${constraint.pattern}\"`,\n }\n }\n }\n }\n }\n\n // 6. 速率限制检查\n if (policy.rate_limit) {\n const rateCheck = globalRateLimiter.check(agentId, policy.credential, policy.rate_limit)\n if (!rateCheck.allowed) {\n const retrySeconds = Math.ceil(rateCheck.retryAfterMs / 1000)\n return {\n result: 'DENIED_ACTION_NOT_ALLOWED',\n message: `速率限制:超过 ${policy.rate_limit.max_calls} 次/${policy.rate_limit.window_seconds}秒,请 ${retrySeconds} 秒后重试`,\n }\n }\n }\n\n // 7. 确定凭证 ID\n const credentialId = policy.credential\n\n return { result: 'ALLOWED', credentialId }\n}\n","import crypto from 'node:crypto'\n\nconst ALGORITHM = 'aes-256-gcm'\nconst IV_LENGTH = 12 // 96-bit IV for GCM\nconst TAG_LENGTH = 16 // 128-bit auth tag\n\n/**\n * 双层加密方案:\n * - MEK (Master Encryption Key):来自环境变量 BROKER_MASTER_KEY,用于加密 DEK\n * - DEK (Data Encryption Key):每条凭证独立随机生成,用于加密实际数据\n *\n * 存储格式(encryptedData):\n * Base64( IV[12] + AuthTag[16] + CipherText )\n *\n * 存储格式(encryptionKeyId):\n * Base64( DEK_IV[12] + DEK_AuthTag[16] + Encrypted_DEK[32] )\n */\n\nfunction getMasterKey(): Buffer {\n const key = process.env.BROKER_MASTER_KEY\n if (!key) throw new Error('BROKER_MASTER_KEY is not set')\n const buf = Buffer.from(key, 'hex')\n if (buf.length !== 32) throw new Error('BROKER_MASTER_KEY must be 32 bytes (64 hex chars)')\n return buf\n}\n\nfunction encryptWithKey(plaintext: Buffer, key: Buffer): string {\n const iv = crypto.randomBytes(IV_LENGTH)\n const cipher = crypto.createCipheriv(ALGORITHM, key, iv)\n const encrypted = Buffer.concat([cipher.update(plaintext), cipher.final()])\n const tag = cipher.getAuthTag()\n return Buffer.concat([iv, tag, encrypted]).toString('base64')\n}\n\nfunction decryptWithKey(encoded: string, key: Buffer): Buffer {\n const buf = Buffer.from(encoded, 'base64')\n const iv = buf.subarray(0, IV_LENGTH)\n const tag = buf.subarray(IV_LENGTH, IV_LENGTH + TAG_LENGTH)\n const ciphertext = buf.subarray(IV_LENGTH + TAG_LENGTH)\n const decipher = crypto.createDecipheriv(ALGORITHM, key, iv)\n decipher.setAuthTag(tag)\n return Buffer.concat([decipher.update(ciphertext), decipher.final()])\n}\n\nexport interface EncryptedCredential {\n /** AES-256-GCM 加密的凭证数据(Base64) */\n encryptedData: string\n /** 加密后的 DEK(Base64),实际上是 \"encrypted DEK\" */\n encryptionKeyId: string\n}\n\n/**\n * 加密凭证数据\n * @param data 需要加密的凭证对象\n */\nexport function encryptCredential(data: Record<string, unknown>): EncryptedCredential {\n const mek = getMasterKey()\n\n // 1. 生成随机 DEK\n const dek = crypto.randomBytes(32)\n\n // 2. 用 DEK 加密数据\n const plaintext = Buffer.from(JSON.stringify(data), 'utf8')\n const encryptedData = encryptWithKey(plaintext, dek)\n\n // 3. 用 MEK 加密 DEK(encryptionKeyId 存的是\"加密后的 DEK\")\n const encryptionKeyId = encryptWithKey(dek, mek)\n\n return { encryptedData, encryptionKeyId }\n}\n\n/**\n * 解密凭证数据\n */\nexport function decryptCredential(encrypted: EncryptedCredential): Record<string, unknown> {\n const mek = getMasterKey()\n\n // 1. 用 MEK 解密 DEK\n const dek = decryptWithKey(encrypted.encryptionKeyId, mek)\n\n // 2. 用 DEK 解密数据\n const plaintext = decryptWithKey(encrypted.encryptedData, dek)\n\n return JSON.parse(plaintext.toString('utf8')) as Record<string, unknown>\n}\n\n/**\n * 生成 Agent Token\n * 格式:agnt_<base62(32bytes)>\n */\nexport function generateAgentToken(): { token: string; prefix: string } {\n const bytes = crypto.randomBytes(32)\n const token = `agnt_${bytes.toString('base64url')}`\n const prefix = token.substring(0, 12) // \"agnt_\" + 7 chars = 12 chars\n return { token, prefix }\n}\n\n/**\n * 计算 token 的 SHA-256 哈希值\n */\nexport function hashToken(token: string): string {\n return crypto.createHash('sha256').update(token).digest('hex')\n}\n\n/**\n * 生成 MEK(仅用于初始化,运行时从环境变量读取)\n */\nexport function generateMasterKey(): string {\n return crypto.randomBytes(32).toString('hex')\n}\n","import type { DecryptedCredential } from '@broker/shared-types'\nimport { decryptCredential } from '@broker/crypto'\nimport type { LocalStore } from './local-store.js'\n\n/**\n * 从本地配置加载并解密凭证\n * 支持两种模式:\n * 1. 环境变量引用 — token 字段直接包含明文(已在 config-loader 中解析 ${ENV_VAR})\n * 2. AES-256-GCM 加密 — encrypted 字段包含密文,需要 encryption_key 解密\n */\nexport function loadLocalCredential(\n credentialId: string,\n store: LocalStore\n): DecryptedCredential {\n const cred = store.getCredential(credentialId)\n if (!cred) {\n throw new Error(`凭证不存在: ${credentialId}`)\n }\n\n // 模式一:明文 token(来自环境变量引用)\n if (cred.token) {\n return {\n accessToken: cred.token,\n tokenType: 'bearer',\n }\n }\n\n // 模式二:加密存储\n if (cred.encrypted) {\n if (!store.encryptionKey) {\n throw new Error(`凭证 \"${credentialId}\" 使用加密存储,但配置中未设置 encryption_key`)\n }\n\n // 临时设置 BROKER_MASTER_KEY 环境变量,供 @broker/crypto 使用\n const prevKey = process.env.BROKER_MASTER_KEY\n try {\n process.env.BROKER_MASTER_KEY = store.encryptionKey\n const decrypted = decryptCredential({\n encryptedData: cred.encrypted,\n encryptionKeyId: '', // 单层加密模式,encrypted 包含完整密文\n })\n return decrypted as unknown as DecryptedCredential\n } finally {\n if (prevKey !== undefined) {\n process.env.BROKER_MASTER_KEY = prevKey\n } else {\n delete process.env.BROKER_MASTER_KEY\n }\n }\n }\n\n throw new Error(`凭证 \"${credentialId}\" 未配置 token 或 encrypted`)\n}\n","import fs from 'node:fs'\nimport type { AuditConfig } from './config-loader.js'\n\nexport interface AuditEntry {\n timestamp: string\n agentId: string\n connectorId: string\n action: string\n params: Record<string, unknown>\n permissionResult: string\n responseStatus?: number\n errorMessage?: string\n}\n\nconst SENSITIVE_KEYS = ['token', 'secret', 'password', 'key', 'credential']\n\nfunction sanitizeParams(params: Record<string, unknown>): Record<string, unknown> {\n return Object.fromEntries(\n Object.entries(params).map(([k, v]) => [\n k,\n SENSITIVE_KEYS.some(s => k.toLowerCase().includes(s)) ? '[REDACTED]' : v,\n ])\n )\n}\n\n/**\n * 本地审计日志记录器\n * 支持输出到 stdout 或文件\n */\nexport class LocalAuditLogger {\n private config: AuditConfig\n\n constructor(config: AuditConfig) {\n this.config = config\n }\n\n log(entry: Omit<AuditEntry, 'timestamp' | 'params'> & { params: Record<string, unknown> }): void {\n if (!this.config.enabled) return\n\n const record: AuditEntry = {\n ...entry,\n timestamp: new Date().toISOString(),\n params: sanitizeParams(entry.params),\n }\n\n const line = JSON.stringify(record)\n\n if (this.config.output === 'file' && this.config.file) {\n fs.appendFileSync(this.config.file, line + '\\n', 'utf-8')\n } else {\n console.error(`[broker-audit] ${line}`)\n }\n }\n}\n","import { getConnector, listConnectors, expandScopes } from '@broker/connectors'\nimport type { BrokerCallResult } from '@broker/shared-types'\nimport type { LocalStore } from './local-store.js'\nimport { checkLocalPermission } from './local-permission.js'\nimport { loadLocalCredential } from './local-vault.js'\nimport { LocalAuditLogger } from './local-audit.js'\n\nexport interface ToolEntry {\n connector: string\n connectorName: string\n credentialName: string\n action: string\n actionName: string\n description: string\n}\n\n/**\n * 本地 Broker 实例,基于 YAML 配置运行\n * 替代数据库模式下的 @broker/core broker\n */\nexport class LocalBroker {\n private store: LocalStore\n private audit: LocalAuditLogger\n\n constructor(store: LocalStore) {\n this.store = store\n this.audit = new LocalAuditLogger(store.audit)\n }\n\n /**\n * 列出 agent 被授权的所有工具\n */\n listTools(agentId: string, connectorFilter?: string): ToolEntry[] {\n const policies = this.store.getAgentPolicies(agentId)\n const tools: ToolEntry[] = []\n\n for (const policy of policies) {\n const connectorId = policy.credentialConfig.connector\n if (connectorFilter && connectorId !== connectorFilter) continue\n\n const conn = getConnector(connectorId)\n if (!conn) continue\n\n const actions = conn.getActions()\n const expandedActions = expandScopes(policy.actions)\n const actionsAllowAll = expandedActions.length === 0\n || (expandedActions.length === 1 && expandedActions[0] === '*')\n\n for (const action of actions) {\n const fullAction = `${connectorId}:${action.id}`\n if (!actionsAllowAll && !expandedActions.includes(fullAction)) continue\n\n tools.push({\n connector: connectorId,\n connectorName: conn.info.name,\n credentialName: policy.credentialConfig.id,\n action: action.id,\n actionName: action.name,\n description: action.description,\n })\n }\n }\n\n return tools\n }\n\n /**\n * 调用工具\n */\n async callTool(\n agentId: string,\n connectorId: string,\n action: string,\n params: Record<string, unknown>\n ): Promise<BrokerCallResult> {\n // 1. 权限检查\n const permCheck = checkLocalPermission(\n { agentId, connectorId, action, params },\n this.store\n )\n\n if (permCheck.result !== 'ALLOWED' || !permCheck.credentialId) {\n this.audit.log({\n agentId,\n connectorId,\n action: `${connectorId}:${action}`,\n params,\n permissionResult: permCheck.result,\n responseStatus: 403,\n })\n return {\n success: false,\n error: permCheck.message,\n permissionResult: permCheck.result,\n }\n }\n\n // 2. 获取 Connector\n const connector = getConnector(connectorId)\n if (!connector) {\n return { success: false, error: `未知的 connector: ${connectorId}` }\n }\n\n // 3. 加载凭证并执行\n try {\n const credential = loadLocalCredential(permCheck.credentialId, this.store)\n const result = await connector.execute(action, params, credential)\n\n this.audit.log({\n agentId,\n connectorId,\n action: `${connectorId}:${action}`,\n params,\n permissionResult: 'ALLOWED',\n responseStatus: result.httpStatus ?? (result.success ? 200 : 500),\n errorMessage: result.success ? undefined : result.error?.message,\n })\n\n return {\n success: result.success,\n data: result.data,\n error: result.error?.message,\n }\n } catch (err) {\n const message = err instanceof Error ? err.message : 'Internal error'\n this.audit.log({\n agentId,\n connectorId,\n action: `${connectorId}:${action}`,\n params,\n permissionResult: 'ALLOWED',\n responseStatus: 500,\n errorMessage: message,\n })\n return { success: false, error: message }\n }\n }\n}\n","import { hashToken } from '@broker/crypto'\nimport type { LocalStore } from './local-store.js'\nimport type { AgentConfig } from './config-loader.js'\n\n/**\n * 通过 token 认证并返回匹配的 agent\n * @returns 匹配的 agent 配置,未匹配返回 null\n */\nexport function authenticateByToken(token: string, store: LocalStore): AgentConfig | null {\n const hash = hashToken(token)\n return store.findAgentByTokenHash(hash) ?? null\n}\n","import fs from 'node:fs'\nimport { loadConfig } from './config-loader.js'\nimport type { LocalStore } from './local-store.js'\n\n/**\n * 监视 broker.yaml 文件变更,自动重载配置\n * 使用 300ms 防抖避免编辑器保存时多次触发\n * 重载失败时保留旧配置并输出错误日志\n */\nexport class ConfigWatcher {\n private watcher: fs.FSWatcher | null = null\n private debounceTimer: ReturnType<typeof setTimeout> | null = null\n private readonly debounceMs: number\n\n constructor(\n private configPath: string,\n private store: LocalStore,\n opts?: { debounceMs?: number }\n ) {\n this.debounceMs = opts?.debounceMs ?? 300\n }\n\n start(): void {\n if (this.watcher) return\n\n this.watcher = fs.watch(this.configPath, (_eventType) => {\n if (this.debounceTimer) clearTimeout(this.debounceTimer)\n this.debounceTimer = setTimeout(() => this.reload(), this.debounceMs)\n })\n\n this.watcher.on('error', (err) => {\n console.error(`[config-watcher] 监视文件出错: ${err.message}`)\n })\n }\n\n stop(): void {\n if (this.debounceTimer) {\n clearTimeout(this.debounceTimer)\n this.debounceTimer = null\n }\n if (this.watcher) {\n this.watcher.close()\n this.watcher = null\n }\n }\n\n private reload(): void {\n try {\n const config = loadConfig(this.configPath)\n this.store.reload(config)\n console.error(`[config-watcher] 配置已重载: ${this.configPath}`)\n } catch (err) {\n console.error(`[config-watcher] 重载失败(保留旧配置): ${err instanceof Error ? err.message : String(err)}`)\n }\n }\n}\n","import { Command } from 'commander'\nimport { loadConfig, LocalStore, LocalBroker } from '@broker/local-runtime'\nimport { listConnectors } from '@broker/connectors'\nimport { resolveConfigPath, logSuccess, logError, logWarn, log } from '../utils.js'\n\nexport const diagnoseCommand = new Command('diagnose')\n .description('诊断配置和凭证连接状态')\n .option('-c, --config <path>', '配置文件路径', undefined)\n .action(async (opts: { config?: string }) => {\n const configPath = resolveConfigPath(opts.config)\n\n // 1. 加载配置\n log('1. 加载配置...')\n let config\n try {\n config = loadConfig(configPath)\n logSuccess(`配置加载成功 (${config.agents.length} agents, ${config.credentials.length} credentials, ${config.policies.length} policies)`)\n } catch (err) {\n logError(`配置加载失败: ${err instanceof Error ? err.message : String(err)}`)\n process.exitCode = 1\n return\n }\n\n // 2. 检查 Connector 可用性\n log('\\n2. 检查 Connector...')\n const connectors = listConnectors()\n const registeredIds = new Set(connectors.map(c => c.info.id))\n for (const cred of config.credentials) {\n if (registeredIds.has(cred.connector)) {\n logSuccess(`Connector \"${cred.connector}\" 已注册`)\n } else {\n logError(`Connector \"${cred.connector}\" 未注册`)\n }\n }\n\n // 3. 检查凭证有效性(尝试调用简单 API)\n log('\\n3. 测试凭证...')\n const store = new LocalStore(config)\n const broker = new LocalBroker(store)\n\n for (const cred of config.credentials) {\n const testAction = getTestAction(cred.connector)\n if (!testAction) {\n logWarn(`凭证 \"${cred.id}\" (${cred.connector}): 无测试操作`)\n continue\n }\n\n // 找到使用此凭证的 agent\n const policy = config.policies.find(p => p.credential === cred.id)\n if (!policy) {\n logWarn(`凭证 \"${cred.id}\": 无关联策略,跳过测试`)\n continue\n }\n\n try {\n const result = await broker.callTool(policy.agent, cred.connector, testAction, {})\n if (result.success) {\n logSuccess(`凭证 \"${cred.id}\" (${cred.connector}): 连接正常`)\n } else {\n logError(`凭证 \"${cred.id}\" (${cred.connector}): ${result.error}`)\n }\n } catch (err) {\n logError(`凭证 \"${cred.id}\" (${cred.connector}): ${err instanceof Error ? err.message : String(err)}`)\n }\n }\n\n log('\\n诊断完成')\n })\n\nfunction getTestAction(connector: string): string | undefined {\n const testActions: Record<string, string> = {\n github: 'list_repos',\n feishu: 'get_user_info',\n }\n return testActions[connector]\n}\n","import { Command } from 'commander'\nimport { Server } from '@modelcontextprotocol/sdk/server/index.js'\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'\nimport {\n CallToolRequestSchema,\n ListToolsRequestSchema,\n type Tool,\n} from '@modelcontextprotocol/sdk/types.js'\nimport { loadConfig, LocalStore, LocalBroker, authenticateByToken, ConfigWatcher } from '@broker/local-runtime'\nimport { resolveConfigPath, logError } from '../utils.js'\n\nexport const serveCommand = new Command('serve')\n .description('启动 MCP Server(stdio 模式)')\n .option('-c, --config <path>', '配置文件路径', undefined)\n .option('-a, --agent <id>', 'Agent ID(默认使用配置中的第一个 agent)', undefined)\n .action(async (opts: { config?: string; agent?: string }) => {\n const configPath = resolveConfigPath(opts.config)\n\n let config\n try {\n config = loadConfig(configPath)\n } catch (err) {\n logError(`配置加载失败: ${err instanceof Error ? err.message : String(err)}`)\n process.exitCode = 1\n return\n }\n\n const store = new LocalStore(config)\n const broker = new LocalBroker(store)\n\n // Token 认证:优先使用 BROKER_AGENT_TOKEN 环境变量\n let agentId: string\n const envToken = process.env.BROKER_AGENT_TOKEN\n if (envToken) {\n const matched = authenticateByToken(envToken, store)\n if (!matched) {\n logError('BROKER_AGENT_TOKEN 认证失败:token 不匹配任何 agent')\n process.exitCode = 1\n return\n }\n agentId = matched.id\n console.error(`[broker-cli] Token 认证成功: ${matched.name} (${agentId})`)\n } else {\n agentId = opts.agent ?? config.agents[0].id\n }\n\n const agent = store.getAgent(agentId)\n if (!agent) {\n logError(`Agent \"${agentId}\" 不存在`)\n process.exitCode = 1\n return\n }\n\n console.error(`[broker-cli] 使用配置: ${configPath}`)\n console.error(`[broker-cli] Agent: ${agent.name} (${agentId})`)\n\n const server = new Server(\n { name: 'agent-auth-broker', version: '0.1.0' },\n { capabilities: { tools: {} } }\n )\n\n server.setRequestHandler(ListToolsRequestSchema, async () => {\n const tools = broker.listTools(agentId)\n\n const mcpTools: Tool[] = [\n {\n name: 'broker_call',\n description: '通过 Auth Broker 调用第三方服务(GitHub、飞书等),凭证由 Broker 安全管理',\n inputSchema: {\n type: 'object',\n required: ['connector', 'action', 'params'],\n properties: {\n connector: { type: 'string', description: '目标服务名称,如 \"github\"' },\n action: { type: 'string', description: '操作名称,如 \"create_issue\"' },\n params: { type: 'object', description: '操作参数' },\n },\n },\n },\n {\n name: 'broker_list_tools',\n description: '列出当前 Agent 被授权的所有工具',\n inputSchema: {\n type: 'object',\n properties: {\n connector: { type: 'string', description: '可选,过滤特定 connector 的工具' },\n },\n },\n },\n ]\n\n const toolMap = new Map<string, Tool>()\n for (const t of tools) {\n const toolName = `${t.connector}_${t.action}`\n if (toolMap.has(toolName)) continue\n\n toolMap.set(toolName, {\n name: toolName,\n description: `[${t.connectorName}] ${t.description}(凭证:${t.credentialName})`,\n inputSchema: {\n type: 'object',\n description: `调用 ${t.connectorName} 的 ${t.actionName} 操作`,\n },\n })\n }\n\n return { tools: [...mcpTools, ...toolMap.values()] }\n })\n\n server.setRequestHandler(CallToolRequestSchema, async (request) => {\n const { name, arguments: args = {} } = request.params\n const params = args as Record<string, unknown>\n\n try {\n if (name === 'broker_list_tools') {\n const tools = broker.listTools(agentId, params.connector as string | undefined)\n return {\n content: [{ type: 'text', text: JSON.stringify(tools, null, 2) }],\n }\n }\n\n let connector: string\n let action: string\n let callParams: Record<string, unknown>\n\n if (name === 'broker_call') {\n connector = params.connector as string\n action = params.action as string\n callParams = (params.params as Record<string, unknown>) ?? {}\n } else {\n const allTools = broker.listTools(agentId)\n const matched = allTools.find(t => `${t.connector}_${t.action}` === name)\n if (!matched) {\n return {\n content: [{ type: 'text', text: `No permission for tool: ${name}` }],\n isError: true,\n }\n }\n connector = matched.connector\n action = matched.action\n callParams = params\n }\n\n const result = await broker.callTool(agentId, connector, action, callParams)\n\n if (!result.success) {\n const errorText = result.permissionResult\n ? `Permission denied (${result.permissionResult}): ${result.error}`\n : `Error: ${result.error}`\n return { content: [{ type: 'text', text: errorText }], isError: true }\n }\n\n return {\n content: [{ type: 'text', text: JSON.stringify(result.data, null, 2) }],\n }\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err)\n return { content: [{ type: 'text', text: `Internal error: ${message}` }], isError: true }\n }\n })\n\n // 启动配置文件热重载\n const watcher = new ConfigWatcher(configPath, store)\n watcher.start()\n console.error('[broker-cli] 配置热重载已启用')\n\n const transport = new StdioServerTransport()\n await server.connect(transport)\n console.error('[broker-cli] MCP Server started (stdio mode)')\n\n // 进程退出时停止 watcher\n process.on('SIGINT', () => { watcher.stop(); process.exit(0) })\n process.on('SIGTERM', () => { watcher.stop(); process.exit(0) })\n })\n","import { Command } from 'commander'\nimport { listConnectors } from '@broker/connectors'\nimport { encryptCredential, generateMasterKey } from '@broker/crypto'\nimport { resolveConfigPath, readRawConfig, writeConfig, log, logSuccess, logError, logWarn } from '../utils.js'\n\ninterface RawCredential {\n id: string\n connector: string\n token?: string\n encrypted?: string\n}\n\nexport const credentialCommand = new Command('credential')\n .description('凭证管理')\n\ncredentialCommand\n .command('add')\n .description('添加凭证')\n .argument('<connector>', '服务类型 (如 github)')\n .option('-c, --config <path>', '配置文件路径', undefined)\n .option('--id <id>', '凭证 ID(默认为 connector 名称)', undefined)\n .option('--env <name>', '环境变量名称(使用 ${ENV_VAR} 引用)', undefined)\n .option('--token <token>', '直接指定 token 值', undefined)\n .action((connector: string, opts: { config?: string; id?: string; env?: string; token?: string }) => {\n const configPath = resolveConfigPath(opts.config)\n const credentialId = opts.id ?? `${connector}-main`\n\n // 验证 connector 是否支持\n const connectors = listConnectors()\n const supported = connectors.find(c => c.info.id === connector)\n if (!supported) {\n logError(`不支持的 connector: \"${connector}\"`)\n log(`支持的 connector: ${connectors.map(c => c.info.id).join(', ')}`)\n process.exitCode = 1\n return\n }\n\n // 确定 token 值\n let tokenValue: string\n if (opts.env) {\n tokenValue = `\\${${opts.env}}`\n } else if (opts.token) {\n tokenValue = opts.token\n logWarn('直接指定 token 值不安全,建议使用 --env 引用环境变量')\n } else {\n logError('请指定 --env <ENV_VAR> 或 --token <value>')\n process.exitCode = 1\n return\n }\n\n const config = readRawConfig(configPath)\n const credentials = (config.credentials as RawCredential[] | undefined) ?? []\n\n // 检查是否已存在\n const existing = credentials.find(c => c.id === credentialId)\n if (existing) {\n logWarn(`凭证 \"${credentialId}\" 已存在,将被更新`)\n existing.token = tokenValue\n delete existing.encrypted\n } else {\n credentials.push({\n id: credentialId,\n connector,\n token: tokenValue,\n })\n }\n\n config.credentials = credentials\n writeConfig(configPath, config)\n logSuccess(`已添加凭证 \"${credentialId}\" (${connector})`)\n })\n\ncredentialCommand\n .command('list')\n .description('列出所有凭证')\n .option('-c, --config <path>', '配置文件路径', undefined)\n .action((opts: { config?: string }) => {\n const configPath = resolveConfigPath(opts.config)\n const config = readRawConfig(configPath)\n const credentials = (config.credentials as RawCredential[] | undefined) ?? []\n\n if (credentials.length === 0) {\n log('暂无凭证')\n return\n }\n\n log(`凭证列表 (${credentials.length}):`)\n for (const cred of credentials) {\n const source = cred.token?.startsWith('${')\n ? `env: ${cred.token}`\n : cred.encrypted\n ? 'encrypted'\n : 'plaintext'\n log(` - ${cred.id} (${cred.connector}) [${source}]`)\n }\n })\n\ncredentialCommand\n .command('remove')\n .description('移除凭证')\n .argument('<id>', '凭证 ID')\n .option('-c, --config <path>', '配置文件路径', undefined)\n .action((id: string, opts: { config?: string }) => {\n const configPath = resolveConfigPath(opts.config)\n const config = readRawConfig(configPath)\n const credentials = (config.credentials as RawCredential[] | undefined) ?? []\n\n const index = credentials.findIndex(c => c.id === id)\n if (index === -1) {\n logError(`凭证 \"${id}\" 不存在`)\n process.exitCode = 1\n return\n }\n\n credentials.splice(index, 1)\n config.credentials = credentials\n writeConfig(configPath, config)\n logSuccess(`已移除凭证 \"${id}\"`)\n })\n","import { Command } from 'commander'\nimport { resolveConfigPath, readRawConfig, writeConfig, log, logSuccess, logError } from '../utils.js'\n\ninterface RawAgent {\n id: string\n name: string\n}\n\nexport const agentCommand = new Command('agent')\n .description('Agent 管理')\n\nagentCommand\n .command('create')\n .description('创建 Agent')\n .argument('<id>', 'Agent ID')\n .option('-c, --config <path>', '配置文件路径', undefined)\n .option('-n, --name <name>', 'Agent 名称', undefined)\n .action((id: string, opts: { config?: string; name?: string }) => {\n const configPath = resolveConfigPath(opts.config)\n const config = readRawConfig(configPath)\n const agents = (config.agents as RawAgent[] | undefined) ?? []\n\n if (agents.find(a => a.id === id)) {\n logError(`Agent \"${id}\" 已存在`)\n process.exitCode = 1\n return\n }\n\n agents.push({\n id,\n name: opts.name ?? id,\n })\n\n config.agents = agents\n writeConfig(configPath, config)\n logSuccess(`已创建 Agent \"${id}\"`)\n })\n\nagentCommand\n .command('list')\n .description('列出所有 Agent')\n .option('-c, --config <path>', '配置文件路径', undefined)\n .action((opts: { config?: string }) => {\n const configPath = resolveConfigPath(opts.config)\n const config = readRawConfig(configPath)\n const agents = (config.agents as RawAgent[] | undefined) ?? []\n\n if (agents.length === 0) {\n log('暂无 Agent')\n return\n }\n\n log(`Agent 列表 (${agents.length}):`)\n for (const agent of agents) {\n log(` - ${agent.id} (${agent.name})`)\n }\n })\n\nagentCommand\n .command('remove')\n .description('移除 Agent')\n .argument('<id>', 'Agent ID')\n .option('-c, --config <path>', '配置文件路径', undefined)\n .action((id: string, opts: { config?: string }) => {\n const configPath = resolveConfigPath(opts.config)\n const config = readRawConfig(configPath)\n const agents = (config.agents as RawAgent[] | undefined) ?? []\n\n const index = agents.findIndex(a => a.id === id)\n if (index === -1) {\n logError(`Agent \"${id}\" 不存在`)\n process.exitCode = 1\n return\n }\n\n agents.splice(index, 1)\n config.agents = agents\n writeConfig(configPath, config)\n logSuccess(`已移除 Agent \"${id}\"`)\n })\n","import { Command } from 'commander'\nimport { resolveConfigPath, readRawConfig, writeConfig, log, logSuccess, logError } from '../utils.js'\n\ninterface RawPolicy {\n agent: string\n credential: string\n actions: string[]\n param_constraints?: Record<string, { pattern?: string }>\n}\n\nexport const policyCommand = new Command('policy')\n .description('策略管理')\n\npolicyCommand\n .command('set')\n .description('设置或更新策略')\n .argument('<agent>', 'Agent ID')\n .argument('<credential>', '凭证 ID')\n .option('-c, --config <path>', '配置文件路径', undefined)\n .option('--actions <actions>', '允许的操作列表,逗号分隔(\"*\" 表示全部允许)', '*')\n .action((agentId: string, credentialId: string, opts: { config?: string; actions: string }) => {\n const configPath = resolveConfigPath(opts.config)\n const config = readRawConfig(configPath)\n const policies = (config.policies as RawPolicy[] | undefined) ?? []\n\n const actions = opts.actions === '*' ? ['*'] : opts.actions.split(',').map(a => a.trim())\n\n // 查找已有策略\n const existing = policies.find(p => p.agent === agentId && p.credential === credentialId)\n if (existing) {\n existing.actions = actions\n logSuccess(`已更新策略: ${agentId} -> ${credentialId}`)\n } else {\n policies.push({\n agent: agentId,\n credential: credentialId,\n actions,\n })\n logSuccess(`已创建策略: ${agentId} -> ${credentialId}`)\n }\n\n config.policies = policies\n writeConfig(configPath, config)\n })\n\npolicyCommand\n .command('list')\n .description('列出所有策略')\n .option('-c, --config <path>', '配置文件路径', undefined)\n .action((opts: { config?: string }) => {\n const configPath = resolveConfigPath(opts.config)\n const config = readRawConfig(configPath)\n const policies = (config.policies as RawPolicy[] | undefined) ?? []\n\n if (policies.length === 0) {\n log('暂无策略')\n return\n }\n\n log(`策略列表 (${policies.length}):`)\n for (const policy of policies) {\n const actionsStr = policy.actions.includes('*') ? '所有操作' : policy.actions.join(', ')\n log(` - ${policy.agent} -> ${policy.credential}: [${actionsStr}]`)\n }\n })\n\npolicyCommand\n .command('remove')\n .description('移除策略')\n .argument('<agent>', 'Agent ID')\n .argument('<credential>', '凭证 ID')\n .option('-c, --config <path>', '配置文件路径', undefined)\n .action((agentId: string, credentialId: string, opts: { config?: string }) => {\n const configPath = resolveConfigPath(opts.config)\n const config = readRawConfig(configPath)\n const policies = (config.policies as RawPolicy[] | undefined) ?? []\n\n const index = policies.findIndex(p => p.agent === agentId && p.credential === credentialId)\n if (index === -1) {\n logError(`策略 \"${agentId} -> ${credentialId}\" 不存在`)\n process.exitCode = 1\n return\n }\n\n policies.splice(index, 1)\n config.policies = policies\n writeConfig(configPath, config)\n logSuccess(`已移除策略: ${agentId} -> ${credentialId}`)\n })\n","import { Command } from 'commander'\nimport { resolveConfigPath } from '../utils.js'\nimport { startServer } from '../ui/server.js'\n\nexport const uiCommand = new Command('ui')\n .description('启动 File Mode Web UI,可视化管理 broker.yaml')\n .option('-c, --config <path>', '配置文件路径', undefined)\n .option('-p, --port <port>', '服务端口', '3200')\n .action((opts: { config?: string; port: string }) => {\n const configPath = resolveConfigPath(opts.config)\n const port = parseInt(opts.port, 10)\n\n if (isNaN(port) || port < 1 || port > 65535) {\n console.error('Invalid port number')\n process.exitCode = 1\n return\n }\n\n startServer(configPath, port)\n })\n","import http from 'node:http'\nimport { getHtml } from './html.js'\nimport { createHandlers } from './handlers.js'\n\nexport function startServer(configPath: string, port: number): http.Server {\n const handlers = createHandlers(configPath)\n\n const server = http.createServer(async (req, res) => {\n const url = new URL(req.url ?? '/', `http://localhost:${port}`)\n const method = req.method ?? 'GET'\n const pathname = url.pathname\n\n // CORS headers (for local development)\n res.setHeader('Access-Control-Allow-Origin', '*')\n res.setHeader('Access-Control-Allow-Methods', 'GET, POST, DELETE, OPTIONS')\n res.setHeader('Access-Control-Allow-Headers', 'Content-Type')\n\n if (method === 'OPTIONS') {\n res.writeHead(204)\n res.end()\n return\n }\n\n try {\n // Serve HTML\n if (method === 'GET' && pathname === '/') {\n res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' })\n res.end(getHtml())\n return\n }\n\n // API routes\n if (pathname.startsWith('/api/')) {\n const body = method !== 'GET' ? await readBody(req) : undefined\n\n let result: unknown\n\n // Config\n if (method === 'GET' && pathname === '/api/config') {\n result = handlers.getConfigInfo()\n }\n // Agents\n else if (method === 'GET' && pathname === '/api/agents') {\n result = handlers.listAgents()\n }\n else if (method === 'POST' && pathname === '/api/agents') {\n result = handlers.addAgent(body as { id: string; name: string })\n }\n else if (method === 'DELETE' && pathname.startsWith('/api/agents/')) {\n const id = pathname.slice('/api/agents/'.length)\n result = handlers.deleteAgent(decodeURIComponent(id))\n }\n // Credentials\n else if (method === 'GET' && pathname === '/api/credentials') {\n result = handlers.listCredentials()\n }\n else if (method === 'POST' && pathname === '/api/credentials') {\n result = handlers.addCredential(body as { id: string; connector: string; token: string })\n }\n else if (method === 'DELETE' && pathname.startsWith('/api/credentials/')) {\n const id = pathname.slice('/api/credentials/'.length)\n result = handlers.deleteCredential(decodeURIComponent(id))\n }\n // Policies\n else if (method === 'GET' && pathname === '/api/policies') {\n result = handlers.listPolicies()\n }\n else if (method === 'POST' && pathname === '/api/policies') {\n result = handlers.addPolicy(body as { agent: string; credential: string; actions: string[] })\n }\n else if (method === 'DELETE' && pathname === '/api/policies') {\n result = handlers.deletePolicy(body as { agent: string; credential: string })\n }\n // Connectors\n else if (method === 'GET' && pathname === '/api/connectors') {\n result = handlers.listConnectorsInfo()\n }\n // Validate\n else if (method === 'POST' && pathname === '/api/validate') {\n result = handlers.validateConfig()\n }\n else {\n res.writeHead(404)\n res.end(JSON.stringify({ error: 'Not found' }))\n return\n }\n\n res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8' })\n res.end(JSON.stringify(result))\n return\n }\n\n // 404\n res.writeHead(404)\n res.end('Not found')\n } catch (err) {\n const message = err instanceof Error ? err.message : 'Internal server error'\n res.writeHead(400, { 'Content-Type': 'application/json; charset=utf-8' })\n res.end(JSON.stringify({ error: message }))\n }\n })\n\n server.listen(port, () => {\n console.log(`Broker UI running at http://localhost:${port}`)\n console.log(`Config: ${configPath}`)\n console.log('Press Ctrl+C to stop')\n })\n\n return server\n}\n\nfunction readBody(req: http.IncomingMessage): Promise<unknown> {\n return new Promise((resolve, reject) => {\n const chunks: Buffer[] = []\n req.on('data', (chunk: Buffer) => chunks.push(chunk))\n req.on('end', () => {\n const raw = Buffer.concat(chunks).toString('utf-8')\n try {\n resolve(raw ? JSON.parse(raw) : {})\n } catch {\n reject(new Error('Invalid JSON body'))\n }\n })\n req.on('error', reject)\n })\n}\n","/**\n * File Mode UI — 单页面 HTML 模板\n * 内嵌 CSS + JS,零外部依赖\n */\nexport function getHtml(): string {\n return `<!DOCTYPE html>\n<html lang=\"zh-CN\">\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>Agent Auth Broker — File Mode UI</title>\n <style>\n #broker-ui {\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n max-width: 960px;\n margin: 0 auto;\n padding: 24px;\n color: #1a1a1a;\n background: #fafafa;\n min-height: 100vh;\n }\n #broker-ui * { box-sizing: border-box; }\n #broker-ui h1 { font-size: 1.5rem; margin: 0 0 24px; }\n #broker-ui .tabs {\n display: flex;\n border-bottom: 2px solid #e5e7eb;\n margin-bottom: 24px;\n gap: 4px;\n }\n #broker-ui .tab {\n padding: 8px 20px;\n cursor: pointer;\n border: none;\n background: none;\n font-size: 0.95rem;\n color: #6b7280;\n border-bottom: 2px solid transparent;\n margin-bottom: -2px;\n transition: color 0.15s, border-color 0.15s;\n }\n #broker-ui .tab:hover { color: #374151; }\n #broker-ui .tab.active {\n color: #2563eb;\n border-bottom-color: #2563eb;\n font-weight: 600;\n }\n #broker-ui .panel { display: none; }\n #broker-ui .panel.active { display: block; }\n #broker-ui table {\n width: 100%;\n border-collapse: collapse;\n margin-bottom: 20px;\n background: #fff;\n border-radius: 8px;\n overflow: hidden;\n box-shadow: 0 1px 3px rgba(0,0,0,0.08);\n }\n #broker-ui th, #broker-ui td {\n text-align: left;\n padding: 10px 14px;\n border-bottom: 1px solid #f0f0f0;\n font-size: 0.9rem;\n }\n #broker-ui th {\n background: #f9fafb;\n font-weight: 600;\n color: #374151;\n }\n #broker-ui .form-card {\n background: #fff;\n padding: 20px;\n border-radius: 8px;\n box-shadow: 0 1px 3px rgba(0,0,0,0.08);\n margin-bottom: 20px;\n }\n #broker-ui .form-card h3 {\n margin: 0 0 16px;\n font-size: 1rem;\n color: #374151;\n }\n #broker-ui .form-row {\n display: flex;\n gap: 12px;\n margin-bottom: 12px;\n align-items: flex-end;\n }\n #broker-ui .form-group {\n display: flex;\n flex-direction: column;\n gap: 4px;\n flex: 1;\n }\n #broker-ui label {\n font-size: 0.82rem;\n color: #6b7280;\n font-weight: 500;\n }\n #broker-ui input, #broker-ui select {\n padding: 7px 10px;\n border: 1px solid #d1d5db;\n border-radius: 6px;\n font-size: 0.9rem;\n }\n #broker-ui input:focus, #broker-ui select:focus {\n outline: none;\n border-color: #2563eb;\n box-shadow: 0 0 0 2px rgba(37,99,235,0.1);\n }\n #broker-ui button {\n cursor: pointer;\n font-size: 0.9rem;\n }\n #broker-ui .btn {\n padding: 7px 16px;\n border: none;\n border-radius: 6px;\n font-weight: 500;\n }\n #broker-ui .btn-primary {\n background: #2563eb;\n color: #fff;\n }\n #broker-ui .btn-primary:hover { background: #1d4ed8; }\n #broker-ui .btn-danger {\n background: #ef4444;\n color: #fff;\n padding: 4px 10px;\n font-size: 0.82rem;\n }\n #broker-ui .btn-danger:hover { background: #dc2626; }\n #broker-ui .btn-secondary {\n background: #f3f4f6;\n color: #374151;\n border: 1px solid #d1d5db;\n }\n #broker-ui .btn-secondary:hover { background: #e5e7eb; }\n #broker-ui .yaml-preview {\n background: #1e293b;\n color: #e2e8f0;\n padding: 16px;\n border-radius: 8px;\n font-family: 'Menlo', 'Consolas', monospace;\n font-size: 0.85rem;\n line-height: 1.6;\n white-space: pre-wrap;\n overflow-x: auto;\n max-height: 600px;\n overflow-y: auto;\n }\n #broker-ui .toast {\n position: fixed;\n bottom: 24px;\n right: 24px;\n padding: 10px 20px;\n border-radius: 8px;\n color: #fff;\n font-size: 0.9rem;\n opacity: 0;\n transition: opacity 0.3s;\n z-index: 1000;\n }\n #broker-ui .toast.show { opacity: 1; }\n #broker-ui .toast.success { background: #059669; }\n #broker-ui .toast.error { background: #dc2626; }\n #broker-ui .empty {\n text-align: center;\n color: #9ca3af;\n padding: 32px;\n font-size: 0.9rem;\n }\n #broker-ui .header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 24px;\n }\n #broker-ui .header .status {\n font-size: 0.82rem;\n color: #6b7280;\n }\n #broker-ui .badge {\n display: inline-block;\n padding: 2px 8px;\n border-radius: 9999px;\n font-size: 0.75rem;\n font-weight: 500;\n }\n #broker-ui .badge-blue { background: #dbeafe; color: #1d4ed8; }\n #broker-ui .badge-green { background: #dcfce7; color: #15803d; }\n </style>\n</head>\n<body>\n<div id=\"broker-ui\">\n <div class=\"header\">\n <h1>Agent Auth Broker</h1>\n <span class=\"status\" id=\"config-path\"></span>\n </div>\n <div class=\"tabs\">\n <button class=\"tab active\" data-tab=\"agents\">Agents</button>\n <button class=\"tab\" data-tab=\"credentials\">Credentials</button>\n <button class=\"tab\" data-tab=\"policies\">Policies</button>\n <button class=\"tab\" data-tab=\"yaml\">YAML</button>\n </div>\n\n <!-- Agents Panel -->\n <div class=\"panel active\" id=\"panel-agents\">\n <div class=\"form-card\">\n <h3>Add Agent</h3>\n <div class=\"form-row\">\n <div class=\"form-group\">\n <label>ID</label>\n <input id=\"agent-id\" placeholder=\"my-agent\">\n </div>\n <div class=\"form-group\">\n <label>Name</label>\n <input id=\"agent-name\" placeholder=\"My AI Agent\">\n </div>\n <button class=\"btn btn-primary\" onclick=\"addAgent()\">Add</button>\n </div>\n </div>\n <table id=\"agents-table\">\n <thead><tr><th>ID</th><th>Name</th><th></th></tr></thead>\n <tbody></tbody>\n </table>\n </div>\n\n <!-- Credentials Panel -->\n <div class=\"panel\" id=\"panel-credentials\">\n <div class=\"form-card\">\n <h3>Add Credential</h3>\n <div class=\"form-row\">\n <div class=\"form-group\">\n <label>ID</label>\n <input id=\"cred-id\" placeholder=\"github-main\">\n </div>\n <div class=\"form-group\">\n <label>Connector</label>\n <select id=\"cred-connector\"></select>\n </div>\n <div class=\"form-group\">\n <label>Token (env var reference)</label>\n <input id=\"cred-token\" placeholder=\"\\${GITHUB_TOKEN}\">\n </div>\n <button class=\"btn btn-primary\" onclick=\"addCredential()\">Add</button>\n </div>\n </div>\n <table id=\"credentials-table\">\n <thead><tr><th>ID</th><th>Connector</th><th>Token</th><th></th></tr></thead>\n <tbody></tbody>\n </table>\n </div>\n\n <!-- Policies Panel -->\n <div class=\"panel\" id=\"panel-policies\">\n <div class=\"form-card\">\n <h3>Add Policy</h3>\n <div class=\"form-row\">\n <div class=\"form-group\">\n <label>Agent</label>\n <select id=\"policy-agent\"></select>\n </div>\n <div class=\"form-group\">\n <label>Credential</label>\n <select id=\"policy-credential\"></select>\n </div>\n <div class=\"form-group\">\n <label>Actions (comma-separated, * for all)</label>\n <input id=\"policy-actions\" placeholder=\"*\" value=\"*\">\n </div>\n <button class=\"btn btn-primary\" onclick=\"addPolicy()\">Add</button>\n </div>\n </div>\n <table id=\"policies-table\">\n <thead><tr><th>Agent</th><th>Credential</th><th>Actions</th><th></th></tr></thead>\n <tbody></tbody>\n </table>\n </div>\n\n <!-- YAML Preview Panel -->\n <div class=\"panel\" id=\"panel-yaml\">\n <div style=\"display:flex;justify-content:space-between;align-items:center;margin-bottom:12px;\">\n <h3 style=\"margin:0;font-size:1rem;color:#374151;\">broker.yaml</h3>\n <button class=\"btn btn-secondary\" onclick=\"refreshYaml()\">Refresh</button>\n </div>\n <pre class=\"yaml-preview\" id=\"yaml-content\"></pre>\n </div>\n\n <div class=\"toast\" id=\"toast\"></div>\n</div>\n\n<script>\nconst API = '';\n\n// Tab switching\ndocument.querySelectorAll('#broker-ui .tab').forEach(tab => {\n tab.addEventListener('click', () => {\n document.querySelectorAll('#broker-ui .tab').forEach(t => t.classList.remove('active'));\n document.querySelectorAll('#broker-ui .panel').forEach(p => p.classList.remove('active'));\n tab.classList.add('active');\n document.getElementById('panel-' + tab.dataset.tab).classList.add('active');\n if (tab.dataset.tab === 'yaml') refreshYaml();\n if (tab.dataset.tab === 'policies') refreshSelects();\n });\n});\n\nfunction toast(msg, type) {\n const el = document.getElementById('toast');\n el.textContent = msg;\n el.className = 'toast show ' + type;\n setTimeout(() => el.classList.remove('show'), 2500);\n}\n\nasync function api(method, path, body) {\n const opts = { method, headers: { 'Content-Type': 'application/json' } };\n if (body) opts.body = JSON.stringify(body);\n const res = await fetch(API + path, opts);\n if (!res.ok) {\n const text = await res.text();\n throw new Error(text || res.statusText);\n }\n return res.json();\n}\n\n// ===== Agents =====\nasync function loadAgents() {\n try {\n const data = await api('GET', '/api/agents');\n const tbody = document.querySelector('#agents-table tbody');\n if (!data.length) {\n tbody.innerHTML = '<tr><td colspan=\"3\" class=\"empty\">No agents configured</td></tr>';\n return;\n }\n tbody.innerHTML = data.map(a =>\n '<tr><td>' + esc(a.id) + '</td><td>' + esc(a.name) + '</td>' +\n '<td><button class=\"btn btn-danger\" onclick=\"deleteAgent(\\\\'' + esc(a.id) + '\\\\')\">Delete</button></td></tr>'\n ).join('');\n } catch (e) { toast(e.message, 'error'); }\n}\n\nasync function addAgent() {\n const id = document.getElementById('agent-id').value.trim();\n const name = document.getElementById('agent-name').value.trim();\n if (!id || !name) return toast('ID and Name are required', 'error');\n try {\n await api('POST', '/api/agents', { id, name });\n document.getElementById('agent-id').value = '';\n document.getElementById('agent-name').value = '';\n toast('Agent added', 'success');\n loadAgents();\n } catch (e) { toast(e.message, 'error'); }\n}\n\nasync function deleteAgent(id) {\n try {\n await api('DELETE', '/api/agents/' + id);\n toast('Agent deleted', 'success');\n loadAgents();\n } catch (e) { toast(e.message, 'error'); }\n}\n\n// ===== Credentials =====\nasync function loadCredentials() {\n try {\n const data = await api('GET', '/api/credentials');\n const tbody = document.querySelector('#credentials-table tbody');\n if (!data.length) {\n tbody.innerHTML = '<tr><td colspan=\"4\" class=\"empty\">No credentials configured</td></tr>';\n return;\n }\n tbody.innerHTML = data.map(c =>\n '<tr><td>' + esc(c.id) + '</td><td><span class=\"badge badge-blue\">' + esc(c.connector) + '</span></td>' +\n '<td>' + esc(c.token || '(encrypted)') + '</td>' +\n '<td><button class=\"btn btn-danger\" onclick=\"deleteCredential(\\\\'' + esc(c.id) + '\\\\')\">Delete</button></td></tr>'\n ).join('');\n } catch (e) { toast(e.message, 'error'); }\n}\n\nasync function addCredential() {\n const id = document.getElementById('cred-id').value.trim();\n const connector = document.getElementById('cred-connector').value;\n const token = document.getElementById('cred-token').value.trim();\n if (!id || !connector || !token) return toast('All fields are required', 'error');\n try {\n await api('POST', '/api/credentials', { id, connector, token });\n document.getElementById('cred-id').value = '';\n document.getElementById('cred-token').value = '';\n toast('Credential added', 'success');\n loadCredentials();\n } catch (e) { toast(e.message, 'error'); }\n}\n\nasync function deleteCredential(id) {\n try {\n await api('DELETE', '/api/credentials/' + id);\n toast('Credential deleted', 'success');\n loadCredentials();\n } catch (e) { toast(e.message, 'error'); }\n}\n\n// ===== Policies =====\nasync function loadPolicies() {\n try {\n const data = await api('GET', '/api/policies');\n const tbody = document.querySelector('#policies-table tbody');\n if (!data.length) {\n tbody.innerHTML = '<tr><td colspan=\"4\" class=\"empty\">No policies configured</td></tr>';\n return;\n }\n tbody.innerHTML = data.map(p => {\n const acts = Array.isArray(p.actions) ? p.actions.join(', ') : String(p.actions);\n return '<tr><td>' + esc(p.agent) + '</td><td>' + esc(p.credential) + '</td>' +\n '<td><span class=\"badge badge-green\">' + esc(acts) + '</span></td>' +\n '<td><button class=\"btn btn-danger\" onclick=\"deletePolicy(\\\\'' + esc(p.agent) + '\\\\',\\\\'' + esc(p.credential) + '\\\\')\">Delete</button></td></tr>';\n }).join('');\n } catch (e) { toast(e.message, 'error'); }\n}\n\nasync function addPolicy() {\n const agent = document.getElementById('policy-agent').value;\n const credential = document.getElementById('policy-credential').value;\n const actionsStr = document.getElementById('policy-actions').value.trim();\n if (!agent || !credential || !actionsStr) return toast('All fields are required', 'error');\n const actions = actionsStr === '*' ? ['*'] : actionsStr.split(',').map(s => s.trim()).filter(Boolean);\n try {\n await api('POST', '/api/policies', { agent, credential, actions });\n toast('Policy added', 'success');\n loadPolicies();\n } catch (e) { toast(e.message, 'error'); }\n}\n\nasync function deletePolicy(agent, credential) {\n try {\n await api('DELETE', '/api/policies', { agent, credential });\n toast('Policy deleted', 'success');\n loadPolicies();\n } catch (e) { toast(e.message, 'error'); }\n}\n\n// ===== YAML =====\nasync function refreshYaml() {\n try {\n const data = await api('GET', '/api/config');\n document.getElementById('yaml-content').textContent = data.yaml;\n } catch (e) { toast(e.message, 'error'); }\n}\n\n// ===== Helpers =====\nfunction esc(s) { const d = document.createElement('div'); d.textContent = s; return d.innerHTML; }\n\nasync function refreshSelects() {\n try {\n const agents = await api('GET', '/api/agents');\n const creds = await api('GET', '/api/credentials');\n const pAgent = document.getElementById('policy-agent');\n const pCred = document.getElementById('policy-credential');\n pAgent.innerHTML = agents.map(a => '<option value=\"' + esc(a.id) + '\">' + esc(a.id) + '</option>').join('');\n pCred.innerHTML = creds.map(c => '<option value=\"' + esc(c.id) + '\">' + esc(c.id) + '</option>').join('');\n } catch (e) {}\n}\n\nasync function loadConnectors() {\n try {\n const data = await api('GET', '/api/connectors');\n const sel = document.getElementById('cred-connector');\n sel.innerHTML = data.map(c => '<option value=\"' + esc(c.id) + '\">' + esc(c.name) + '</option>').join('');\n } catch (e) {}\n}\n\n// Initial load\nloadAgents();\nloadCredentials();\nloadPolicies();\nloadConnectors();\n\n// Show config path\napi('GET', '/api/config').then(d => {\n document.getElementById('config-path').textContent = d.path || '';\n}).catch(() => {});\n</script>\n</body>\n</html>`\n}\n","import { stringify as stringifyYaml } from 'yaml'\nimport { readRawConfig, writeConfig } from '../utils.js'\nimport { listConnectors } from '@broker/connectors'\nimport { validateConfigFile } from '@broker/local-runtime'\n\ninterface RawAgent {\n id: string\n name: string\n token_hash?: string\n token_prefix?: string\n}\n\ninterface RawCredential {\n id: string\n connector: string\n token?: string\n encrypted?: string\n}\n\ninterface RawPolicy {\n agent: string\n credential: string\n actions: string[]\n param_constraints?: Record<string, { pattern?: string }>\n}\n\nexport function createHandlers(configPath: string) {\n function getConfig() {\n return readRawConfig(configPath)\n }\n\n function saveConfig(config: Record<string, unknown>) {\n writeConfig(configPath, config)\n }\n\n return {\n // GET /api/config — 返回脱敏的 YAML 和路径\n getConfigInfo() {\n const config = getConfig()\n // 对 token 脱敏显示\n const sanitized = JSON.parse(JSON.stringify(config))\n const creds = (sanitized.credentials ?? []) as RawCredential[]\n for (const c of creds) {\n if (c.token && !c.token.startsWith('${')) {\n c.token = '***'\n }\n }\n // 生成 YAML 预览\n const yaml = stringifyYaml(sanitized, { lineWidth: 120 })\n return { yaml, path: configPath }\n },\n\n // GET /api/agents\n listAgents(): RawAgent[] {\n const config = getConfig()\n return (config.agents as RawAgent[] | undefined) ?? []\n },\n\n // POST /api/agents\n addAgent(body: { id: string; name: string }) {\n const config = getConfig()\n const agents = (config.agents as RawAgent[] | undefined) ?? []\n if (agents.find(a => a.id === body.id)) {\n throw new Error(`Agent \"${body.id}\" already exists`)\n }\n agents.push({ id: body.id, name: body.name })\n config.agents = agents\n saveConfig(config)\n return { ok: true }\n },\n\n // DELETE /api/agents/:id\n deleteAgent(id: string) {\n const config = getConfig()\n const agents = (config.agents as RawAgent[] | undefined) ?? []\n const index = agents.findIndex(a => a.id === id)\n if (index === -1) throw new Error(`Agent \"${id}\" not found`)\n agents.splice(index, 1)\n config.agents = agents\n // 同时移除关联策略\n const policies = (config.policies as RawPolicy[] | undefined) ?? []\n config.policies = policies.filter(p => p.agent !== id)\n saveConfig(config)\n return { ok: true }\n },\n\n // GET /api/credentials\n listCredentials(): Array<{ id: string; connector: string; token?: string }> {\n const config = getConfig()\n const creds = (config.credentials as RawCredential[] | undefined) ?? []\n return creds.map(c => ({\n id: c.id,\n connector: c.connector,\n token: c.token ? (c.token.startsWith('${') ? c.token : '***') : undefined,\n }))\n },\n\n // POST /api/credentials\n addCredential(body: { id: string; connector: string; token: string }) {\n const config = getConfig()\n const creds = (config.credentials as RawCredential[] | undefined) ?? []\n if (creds.find(c => c.id === body.id)) {\n throw new Error(`Credential \"${body.id}\" already exists`)\n }\n creds.push({ id: body.id, connector: body.connector, token: body.token })\n config.credentials = creds\n saveConfig(config)\n return { ok: true }\n },\n\n // DELETE /api/credentials/:id\n deleteCredential(id: string) {\n const config = getConfig()\n const creds = (config.credentials as RawCredential[] | undefined) ?? []\n const index = creds.findIndex(c => c.id === id)\n if (index === -1) throw new Error(`Credential \"${id}\" not found`)\n creds.splice(index, 1)\n config.credentials = creds\n // 同时移除关联策略\n const policies = (config.policies as RawPolicy[] | undefined) ?? []\n config.policies = policies.filter(p => p.credential !== id)\n saveConfig(config)\n return { ok: true }\n },\n\n // GET /api/policies\n listPolicies(): RawPolicy[] {\n const config = getConfig()\n return (config.policies as RawPolicy[] | undefined) ?? []\n },\n\n // POST /api/policies\n addPolicy(body: { agent: string; credential: string; actions: string[] }) {\n const config = getConfig()\n const policies = (config.policies as RawPolicy[] | undefined) ?? []\n const existing = policies.find(p => p.agent === body.agent && p.credential === body.credential)\n if (existing) {\n existing.actions = body.actions\n } else {\n policies.push({ agent: body.agent, credential: body.credential, actions: body.actions })\n }\n config.policies = policies\n saveConfig(config)\n return { ok: true }\n },\n\n // DELETE /api/policies\n deletePolicy(body: { agent: string; credential: string }) {\n const config = getConfig()\n const policies = (config.policies as RawPolicy[] | undefined) ?? []\n const index = policies.findIndex(p => p.agent === body.agent && p.credential === body.credential)\n if (index === -1) throw new Error('Policy not found')\n policies.splice(index, 1)\n config.policies = policies\n saveConfig(config)\n return { ok: true }\n },\n\n // GET /api/connectors\n listConnectorsInfo() {\n return listConnectors().map(c => ({ id: c.info.id, name: c.info.name }))\n },\n\n // POST /api/validate\n validateConfig() {\n try {\n return validateConfigFile(configPath)\n } catch (e) {\n return { valid: false, errors: [(e as Error).message] }\n }\n },\n }\n}\n","import { Command } from 'commander'\nimport { generateAgentToken, hashToken } from '@broker/crypto'\nimport { resolveConfigPath, readRawConfig, writeConfig, log, logSuccess, logError } from '../utils.js'\n\ninterface RawAgent {\n id: string\n name: string\n token_hash?: string\n token_prefix?: string\n}\n\nexport const tokenCommand = new Command('token')\n .description('Agent Token 管理')\n\ntokenCommand\n .command('generate')\n .description('为 Agent 生成认证 Token')\n .argument('<agent>', 'Agent ID')\n .option('-c, --config <path>', '配置文件路径', undefined)\n .option('-f, --force', '覆盖已有 token', false)\n .action((agentId: string, opts: { config?: string; force: boolean }) => {\n const configPath = resolveConfigPath(opts.config)\n const config = readRawConfig(configPath)\n const agents = (config.agents as RawAgent[] | undefined) ?? []\n\n const agent = agents.find(a => a.id === agentId)\n if (!agent) {\n logError(`Agent \"${agentId}\" 不存在`)\n process.exitCode = 1\n return\n }\n\n if (agent.token_hash && !opts.force) {\n logError(`Agent \"${agentId}\" 已有 token(prefix: ${agent.token_prefix}),使用 --force 覆盖`)\n process.exitCode = 1\n return\n }\n\n const { token, prefix } = generateAgentToken()\n agent.token_hash = hashToken(token)\n agent.token_prefix = prefix\n\n config.agents = agents\n writeConfig(configPath, config)\n\n logSuccess(`Token 已生成`)\n log('')\n log(` Token: ${token}`)\n log(` Prefix: ${prefix}`)\n log('')\n log(' 请妥善保存此 token,它不会再次显示。')\n log(' 在 MCP 配置中设置环境变量:')\n log(` BROKER_AGENT_TOKEN=\"${token}\"`)\n })\n\ntokenCommand\n .command('revoke')\n .description('撤销 Agent 的 Token')\n .argument('<agent>', 'Agent ID')\n .option('-c, --config <path>', '配置文件路径', undefined)\n .action((agentId: string, opts: { config?: string }) => {\n const configPath = resolveConfigPath(opts.config)\n const config = readRawConfig(configPath)\n const agents = (config.agents as RawAgent[] | undefined) ?? []\n\n const agent = agents.find(a => a.id === agentId)\n if (!agent) {\n logError(`Agent \"${agentId}\" 不存在`)\n process.exitCode = 1\n return\n }\n\n if (!agent.token_hash) {\n logError(`Agent \"${agentId}\" 没有 token`)\n process.exitCode = 1\n return\n }\n\n delete agent.token_hash\n delete agent.token_prefix\n\n config.agents = agents\n writeConfig(configPath, config)\n logSuccess(`已撤销 Agent \"${agentId}\" 的 token`)\n })\n\ntokenCommand\n .command('list')\n .description('列出所有 Agent 的 Token 状态')\n .option('-c, --config <path>', '配置文件路径', undefined)\n .action((opts: { config?: string }) => {\n const configPath = resolveConfigPath(opts.config)\n const config = readRawConfig(configPath)\n const agents = (config.agents as RawAgent[] | undefined) ?? []\n\n if (agents.length === 0) {\n log('暂无 Agent')\n return\n }\n\n log(`Agent Token 状态 (${agents.length}):`)\n for (const agent of agents) {\n if (agent.token_hash) {\n log(` - ${agent.id} (${agent.name}): token set (prefix: ${agent.token_prefix})`)\n } else {\n log(` - ${agent.id} (${agent.name}): no token`)\n }\n }\n })\n","import { Command } from 'commander'\nimport { loadConfig, LocalStore, LocalBroker, authenticateByToken, checkLocalPermission } from '@broker/local-runtime'\nimport { resolveConfigPath, log, logError, logSuccess } from '../utils.js'\n\nexport const testCommand = new Command('test')\n .description('测试调用 connector 操作')\n .argument('<connector>', 'Connector 名称,如 \"github\"')\n .argument('<action>', '操作名称,如 \"list_repos\"')\n .option('-c, --config <path>', '配置文件路径', undefined)\n .option('-a, --agent <id>', 'Agent ID', undefined)\n .option('-p, --params <json>', '操作参数(JSON 格式)', '{}')\n .option('--dry-run', '仅执行权限检查,不实际调用 API', false)\n .action(async (\n connector: string,\n action: string,\n opts: { config?: string; agent?: string; params: string; dryRun: boolean }\n ) => {\n const configPath = resolveConfigPath(opts.config)\n\n let config\n try {\n config = loadConfig(configPath)\n } catch (err) {\n logError(`配置加载失败: ${err instanceof Error ? err.message : String(err)}`)\n process.exitCode = 1\n return\n }\n\n const store = new LocalStore(config)\n\n // 确定 agent\n let agentId: string\n const envToken = process.env.BROKER_AGENT_TOKEN\n if (envToken) {\n const matched = authenticateByToken(envToken, store)\n if (!matched) {\n logError('BROKER_AGENT_TOKEN 认证失败')\n process.exitCode = 1\n return\n }\n agentId = matched.id\n } else {\n agentId = opts.agent ?? config.agents[0].id\n }\n\n // 解析参数\n let params: Record<string, unknown>\n try {\n params = JSON.parse(opts.params)\n } catch {\n logError('参数格式错误,请提供有效的 JSON')\n process.exitCode = 1\n return\n }\n\n log(`Agent: ${agentId}`)\n log(`Connector: ${connector}`)\n log(`Action: ${action}`)\n log(`Params: ${JSON.stringify(params)}`)\n log('')\n\n // 权限检查\n const permResult = checkLocalPermission(\n { agentId, connectorId: connector, action, params },\n store\n )\n\n if (permResult.result !== 'ALLOWED') {\n logError(`权限检查失败: ${permResult.result}`)\n log(` ${permResult.message ?? ''}`)\n process.exitCode = 1\n return\n }\n\n logSuccess('权限检查通过')\n\n if (opts.dryRun) {\n log('(dry-run 模式,跳过实际调用)')\n return\n }\n\n // 实际调用\n log('')\n log('执行中...')\n const broker = new LocalBroker(store)\n const result = await broker.callTool(agentId, connector, action, params)\n\n if (result.success) {\n logSuccess('调用成功')\n log(JSON.stringify(result.data, null, 2))\n } else {\n logError(`调用失败: ${result.error}`)\n process.exitCode = 1\n }\n })\n"],"mappings":"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AAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;A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","names":["Command","fs","stringifyYaml","fs","stringifyYaml","Command","fs","path","parseYaml","path","fs","fs","fs","Command","Command","Command","connectors","Command","Command","Command","Command","connectors","Command","Command","Command","Command","Command","stringifyYaml","stringifyYaml","Command","Command","Command","Command","Command","Command"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "agent-auth-broker",
|
|
3
|
+
"version": "0.0.2",
|
|
4
|
+
"description": "AI Agent 集中式凭证管理与授权代理 CLI 工具",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"bin": {
|
|
8
|
+
"broker": "./dist/index.js"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"dist"
|
|
12
|
+
],
|
|
13
|
+
"dependencies": {
|
|
14
|
+
"@modelcontextprotocol/sdk": "^1.12.0",
|
|
15
|
+
"commander": "^13.1.0",
|
|
16
|
+
"yaml": "^2.7.0",
|
|
17
|
+
"zod": "^3.23.8"
|
|
18
|
+
},
|
|
19
|
+
"devDependencies": {
|
|
20
|
+
"@types/node": "^20.19.37",
|
|
21
|
+
"tsup": "^8.5.1",
|
|
22
|
+
"typescript": "^5.7.0",
|
|
23
|
+
"@broker/connectors": "0.1.0",
|
|
24
|
+
"@broker/crypto": "0.1.0",
|
|
25
|
+
"@broker/local-runtime": "0.1.0",
|
|
26
|
+
"@broker/shared-types": "0.1.0"
|
|
27
|
+
},
|
|
28
|
+
"keywords": [
|
|
29
|
+
"ai",
|
|
30
|
+
"agent",
|
|
31
|
+
"auth",
|
|
32
|
+
"broker",
|
|
33
|
+
"mcp",
|
|
34
|
+
"credential",
|
|
35
|
+
"security"
|
|
36
|
+
],
|
|
37
|
+
"repository": {
|
|
38
|
+
"type": "git",
|
|
39
|
+
"url": "https://github.com/user/agent-auth-broker"
|
|
40
|
+
},
|
|
41
|
+
"scripts": {
|
|
42
|
+
"build": "tsup",
|
|
43
|
+
"dev": "node --watch --experimental-strip-types src/index.ts",
|
|
44
|
+
"clean": "rm -rf dist"
|
|
45
|
+
}
|
|
46
|
+
}
|