weifuwu 0.82.1 → 0.82.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.
@@ -30,6 +30,9 @@ export interface AgentTool {
30
30
  }
31
31
  export interface AgentConfig {
32
32
  model?: string;
33
+ /** BYOK:per-call 覆盖全局 apiKey/baseUrl(租户自带模型 Key——商业化 G4) */
34
+ apiKey?: string;
35
+ baseUrl?: string;
33
36
  systemPrompt: string;
34
37
  tools: AgentTool[];
35
38
  /** 默认 10 */
@@ -140,6 +140,10 @@ export interface ToolDefinition {
140
140
  }
141
141
  export interface ChatParams {
142
142
  model?: string;
143
+ /** BYOK:per-call 覆盖全局 apiKey(租户自带模型 Key——商业化 G4) */
144
+ apiKey?: string;
145
+ /** BYOK:per-call 覆盖全局端点(OpenAI 兼容任意服务商) */
146
+ baseUrl?: string;
143
147
  messages: ChatMessage[];
144
148
  temperature?: number;
145
149
  max_tokens?: number;
package/dist/index.js CHANGED
@@ -1696,6 +1696,28 @@ function userSystem(options) {
1696
1696
  currentUser = user;
1697
1697
  return { ...session, user };
1698
1698
  },
1699
+ async ssoLogin(email2, opts) {
1700
+ const normalized = normalizeEmail(email2);
1701
+ let user;
1702
+ const existing = await sql.query.from(USERS_TABLE).select("id", "email", "name", "role", "tenant").where({ email: normalized }).run();
1703
+ if (existing.length) {
1704
+ user = existing[0];
1705
+ } else {
1706
+ const rows = await sql.query.insert(USERS_TABLE).values({ email: normalized, password_hash: null, name: opts?.name ?? null, role: null, tenant: null }).returning("id", "email", "name", "role", "tenant").run();
1707
+ user = rows[0];
1708
+ }
1709
+ let appId;
1710
+ if (opts?.appId) {
1711
+ const member = await findMemberRole(opts.appId, user.id);
1712
+ if (!member) {
1713
+ await sql.query.insert(MEMBER_TABLE).values({ app_id: opts.appId, user_id: user.id, role: "member", invited_by: null }).run();
1714
+ }
1715
+ appId = opts.appId;
1716
+ }
1717
+ const session = await issueSession(user, appId ? { appId, role: "member" } : void 0);
1718
+ currentUser = user;
1719
+ return { ...session, user };
1720
+ },
1699
1721
  async createInvite(appId, opts) {
1700
1722
  if (!currentUser) throw new HttpError("Unauthorized", 401);
1701
1723
  const role = await findMemberRole(appId, currentUser.id);
@@ -1736,7 +1758,7 @@ function userSystem(options) {
1736
1758
  CREATE TABLE IF NOT EXISTS ${USERS_TABLE} (
1737
1759
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
1738
1760
  email TEXT NOT NULL UNIQUE,
1739
- password_hash TEXT NOT NULL,
1761
+ password_hash TEXT,
1740
1762
  name TEXT,
1741
1763
  role TEXT,
1742
1764
  tenant TEXT,
@@ -1744,6 +1766,7 @@ function userSystem(options) {
1744
1766
  created_at TIMESTAMPTZ NOT NULL DEFAULT now()
1745
1767
  )
1746
1768
  `);
1769
+ await sql.unsafe(`ALTER TABLE ${USERS_TABLE} ALTER COLUMN password_hash DROP NOT NULL`);
1747
1770
  await sql.unsafe(`
1748
1771
  CREATE TABLE IF NOT EXISTS ${SESSIONS_TABLE} (
1749
1772
  token_hash TEXT PRIMARY KEY,
@@ -2941,9 +2964,14 @@ function createEmbeddingClient(ebd) {
2941
2964
  };
2942
2965
  }
2943
2966
  function createAiClient(opts) {
2944
- const endpoint = `${opts.baseUrl.replace(/\/$/, "")}/chat/completions`;
2945
- const headers = { "Content-Type": "application/json", Authorization: `Bearer ${opts.apiKey}` };
2946
2967
  const embedding = createEmbeddingClient(opts.embedding);
2968
+ function endpointFor(params) {
2969
+ const base2 = params.baseUrl ?? opts.baseUrl;
2970
+ return `${base2.replace(/\/$/, "")}/chat/completions`;
2971
+ }
2972
+ function headersFor(params) {
2973
+ return { "Content-Type": "application/json", Authorization: `Bearer ${params.apiKey ?? opts.apiKey}` };
2974
+ }
2947
2975
  const approvals = /* @__PURE__ */ new Map();
2948
2976
  function approve(response) {
2949
2977
  const resolve3 = approvals.get(response.id);
@@ -2985,9 +3013,9 @@ function createAiClient(opts) {
2985
3013
  return calls;
2986
3014
  }
2987
3015
  async function chat(params, options) {
2988
- const res = await fetch(endpoint, {
3016
+ const res = await fetch(endpointFor(params), {
2989
3017
  method: "POST",
2990
- headers,
3018
+ headers: headersFor(params),
2991
3019
  body: JSON.stringify({ ...params, model: params.model ?? opts.defaultModel, stream: false }),
2992
3020
  signal: options?.signal
2993
3021
  });
@@ -3020,9 +3048,9 @@ function createAiClient(opts) {
3020
3048
  const { emit, signal } = stepOpts;
3021
3049
  let res;
3022
3050
  try {
3023
- res = await fetch(endpoint, {
3051
+ res = await fetch(endpointFor(params), {
3024
3052
  method: "POST",
3025
- headers,
3053
+ headers: headersFor(params),
3026
3054
  body: JSON.stringify({ ...params, model: params.model ?? opts.defaultModel, stream: true }),
3027
3055
  signal
3028
3056
  });
@@ -3169,7 +3197,7 @@ function createAgent(client, config) {
3169
3197
  emit("wf:step", { type: "llm" });
3170
3198
  let finish = { content: "", toolCalls: [] };
3171
3199
  await client.streamStep(
3172
- { model: config.model, messages: all, tools: toolDefs },
3200
+ { model: config.model, apiKey: config.apiKey, baseUrl: config.baseUrl, messages: all, tools: toolDefs },
3173
3201
  {
3174
3202
  emit,
3175
3203
  signal,
@@ -136,6 +136,15 @@ export interface AuthApi {
136
136
  refreshToken: string;
137
137
  user: User;
138
138
  }>;
139
+ /** SSO 登录(无密码):按 email 找或建平台账号;带 appId 时自动加成员并签发应用会话 */
140
+ ssoLogin(email: string, opts?: {
141
+ appId?: string;
142
+ name?: string;
143
+ }): Promise<{
144
+ token: string;
145
+ refreshToken: string;
146
+ user: User;
147
+ }>;
139
148
  /** owner 生成邀请 token(7 天有效,可选绑定 email/role) */
140
149
  createInvite(appId: string, opts: {
141
150
  email?: string;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "weifuwu",
3
3
  "type": "module",
4
- "version": "0.82.1",
4
+ "version": "0.82.2",
5
5
  "description": "AI SaaS framework — (req, ctx) => Response",
6
6
  "exports": {
7
7
  ".": {